diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/typenum | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/typenum')
23 files changed, 8053 insertions, 0 deletions
diff --git a/third_party/rust/typenum/.cargo-checksum.json b/third_party/rust/typenum/.cargo-checksum.json new file mode 100644 index 0000000000..f4aa86ca1b --- /dev/null +++ b/third_party/rust/typenum/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"9990a2e222cad7eff8e8eec1e74a57e9aeecdb831e4a54208e7d5efd7b95432e","Cargo.toml":"e03aa2d8e8102aacf33c0dd58c8006bf7101b335d079d6b862870a471e488a3c","LICENSE":"db11fec9946737df39ca3898d9cd8c10ec6f6c3a884a6802b0ad0b81b4e8f23a","LICENSE-APACHE":"516b24e051bf5630880ebbd55c40a25ce9552ebaf8970a53e8976eb70e522406","LICENSE-MIT":"a825bd853ab71619a4923d7b4311221427848070ff44d990da39b0b274c1683f","README.md":"ab1dc7cd2ee48283b3a511463785da5dd3a93b387a26beb89185442eb66c7471","build/generic_const_mappings.rs":"b71d125b1a6e9696c5c0b24520c92aeca45fa14aa1189f1eee53b317d74de54a","build/main.rs":"006693936308cb1eca0768f94212ccdfe52951c79f64fd18f5c58124c1448f20","build/op.rs":"64ced5cb4016b28daa788e9f74713f1cb432af98c645f60641b90425f10741ec","build/tests.rs":"4e74a95412d9a7ad1dfba36cced27e3f723ab474a4b695d97c6adc30c5850d44","clippy.toml":"493258e6a4be8bbb66ecbc4236d8f4964f867d4bcddd5f13897aa655a206af7b","rustfmt.toml":"4953048a8d16fba8736c5cdb65ce418e462317a79793f16f79023f571f3fd5ce","src/array.rs":"d86f463e1f24a49073afc3ad875ea9b69ccfa85dad4c2738e022031c006f1087","src/bit.rs":"a658ddf3b93db9eeb8fb3eb659f67356de40d1bccf544672d650ae7be1d8e215","src/int.rs":"4adaadb711694426a6af1e7fbb54f33d668992ac0a674b77f0894a1a2213fda8","src/lib.rs":"c4368d0aedecd6e2dfe0d4716d55474a7f17e5bd7a4e59efb7a9e0494c9a25bc","src/marker_traits.rs":"5a58d16edc16853b4b793a6b46068d926911273aa9dc57fd9dc64df77986b7dd","src/operator_aliases.rs":"c190f5bcf9f674c2f2bb56886a45ff548e5acb9320b406cbc45204ef3bac46d5","src/private.rs":"e2ab0e29eacdedfe4182aa0567ac8e9cb53680dc04e1d75e197321b4e1446111","src/type_operators.rs":"cf04a1a4601b2d486e9e737130f1bff3e0a750fefe32b9f11c3bed0dad2c1a10","src/uint.rs":"a8872e9337e77158ec0d1cdf723dd8fefec22b58676e765098206f6cb24ba5db","tests/test.rs":"92139fa86ffcacc1dff60e6fc36420c850d70dc814bd21dc18e87857553c6cea"},"package":"497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"}
\ No newline at end of file diff --git a/third_party/rust/typenum/CHANGELOG.md b/third_party/rust/typenum/CHANGELOG.md new file mode 100644 index 0000000000..fb3bcb5ae9 --- /dev/null +++ b/third_party/rust/typenum/CHANGELOG.md @@ -0,0 +1,114 @@ +# Changelog + +This project follows semantic versioning. + +The MSRV (Minimum Supported Rust Version) is 1.37.0, and typenum is tested +against this Rust version. + +### Unreleased + +### 1.16.0 (2022-12-05) +- [added] `const INT` field to the `ToInt` trait. +- [added] `const-generics` field with `U<N>` mapping wher `N` is a const generic. + +### 1.15.0 (2021-12-25) +- [fixed] Cross-compilation issue due to doing math in build script. (PR #177) +- [added] New feature `scale_info` for using inside + [Substrate](https://github.com/paritytech/substrate.git)-based runtimes (PR + #175) + +### 1.14.0 (2021-09-01) +- [changed] Sealed all marker traits. Documentation already stated that these + should not be implemented outside the crate, so this is not considered a + breaking change. + +### 1.13.0 (2021-03-12) +- [changed] MSRV from 1.22.0 to 1.37.0. +- [fixed] `op` macro with 2018 edition import. +- [changed] Allowed calling `assert_type_eq` and `assert_type` at top level. +- [added] Marker trait `Zero` for `Z0`, `U0`, and `B0`. +- [added] Implementation of `Pow` trait for f32 and f64 with negative exponent. +- [added] Trait `ToInt`. + +### 1.12.0 (2020-04-13) +- [added] Feature `force_unix_path_separator` to support building without Cargo. +- [added] Greatest common divisor operator `Gcd` with alias `Gcf`. +- [added] `gcd` to the `op!` macro. +- [changed] Added `Copy` bound to `Rhs` of `Mul<Rhs>` impl for `<TArr<V, A>`. +- [changed] Added `Copy` bound to `Rhs` of `Div<Rhs>` impl for `<TArr<V, A>`. +- [changed] Added `Copy` bound to `Rhs` of `PartialDiv<Rhs>` impl for `<TArr<V, A>`. +- [changed] Added `Copy` bound to `Rhs` of `Rem<Rhs>` impl for `<TArr<V, A>`. +- [fixed] Make all functions #[inline]. + +### 1.11.2 (2019-08-26) +- [fixed] Cross compilation from Linux to Windows. + +### 1.11.1 (2019-08-25) +- [fixed] Builds on earlier Rust builds again and added Rust 1.22.0 to Travis to + prevent future breakage. + +### 1.11.0 (2019-08-25) +- [added] Integer `log2` to the `op!` macro. +- [added] Integer binary logarithm operator `Logarithm2` with alias `Log2`. +- [changed] Removed `feature(i128_type)` when running with the `i128` + feature. Kept the feature flag. for typenum to maintain compatibility with + old Rust versions. +- [added] Integer `sqrt` to the `op!` macro. +- [added] Integer square root operator `SquareRoot` with alias `Sqrt`. +- [fixed] Bug with attempting to create U1024 type alias twice. + +### 1.10.0 (2018-03-11) +- [added] The `PowerOfTwo` marker trait. +- [added] Associated constants for `Bit`, `Unsigned`, and `Integer`. + +### 1.9.0 (2017-05-14) +- [added] The `Abs` type operater and corresponding `AbsVal` alias. +- [added] The feature `i128` that enables creating 128-bit integers from + typenums. +- [added] The `assert_type!` and `assert_type_eq!` macros. +- [added] Operators to the `op!` macro, including those performed by `cmp!`. +- [fixed] Bug in `op!` macro involving functions and convoluted expressions. +- [deprecated] The `cmp!` macro. + +### 1.8.0 (2017-04-12) +- [added] The `op!` macro for conveniently performing type-level operations. +- [added] The `cmp!` macro for conveniently performing type-level comparisons. +- [added] Some comparison type-operators that are used by the `cmp!` macro. + +### 1.7.0 (2017-03-24) +- [added] Type operators `Min` and `Max` with accompanying aliases `Minimum` and + `Maximum` + +### 1.6.0 (2017-02-24) +- [fixed] Bug in `Array` division. +- [fixed] Bug where `Rem` would sometimes exit early with the wrong answer. +- [added] `PartialDiv` operator that performs division as a partial function -- + it's defined only when there is no remainder. + +### 1.5.2 (2017-02-04) +- [fixed] Bug between `Div` implementation and type system. + +### 1.5.1 (2016-11-08) +- [fixed] Expanded implementation of `Pow` for primitives. + +### 1.5.0 (2016-11-03) +- [added] Functions to the `Pow` and `Len` traits. This is *technically* a + breaking change, but it would only break someone's code if they have a custom + impl for `Pow`. I would be very surprised if that is anyone other than me. + +### 1.4.0 (2016-10-29) +- [added] Type-level arrays of type-level integers. (PR #66) +- [added] The types in this crate are now instantiable. (Issue #67, PR #68) + +### 1.3.1 (2016-03-31) +- [fixed] Bug with recent nightlies. + +### 1.3.0 (2016-02-07) +- [changed] Removed dependency on libstd. (Issue #53, PR #55) +- [changed] Reorganized module structure. (PR #57) + +### 1.2.0 (2016-01-03) +- [added] This change log! +- [added] Convenience type aliases for operators. (Issue #48, PR #50) +- [added] Types in this crate now derive all possible traits. (Issue #42, PR + #51) diff --git a/third_party/rust/typenum/Cargo.toml b/third_party/rust/typenum/Cargo.toml new file mode 100644 index 0000000000..e762eb7c86 --- /dev/null +++ b/third_party/rust/typenum/Cargo.toml @@ -0,0 +1,47 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.37.0" +name = "typenum" +version = "1.16.0" +authors = [ + "Paho Lurie-Gregg <paho@paholg.com>", + "Andre Bogus <bogusandre@gmail.com>", +] +build = "build/main.rs" +description = """ +Typenum is a Rust library for type-level numbers evaluated at + compile time. It currently supports bits, unsigned integers, and signed + integers. It also provides a type-level array of type-level numbers, but its + implementation is incomplete.""" +documentation = "https://docs.rs/typenum" +readme = "README.md" +categories = ["no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/paholg/typenum" + +[lib] +name = "typenum" + +[dependencies.scale-info] +version = "1.0" +optional = true +default-features = false + +[features] +const-generics = [] +force_unix_path_separator = [] +i128 = [] +no_std = [] +scale_info = ["scale-info/derive"] +strict = [] diff --git a/third_party/rust/typenum/LICENSE b/third_party/rust/typenum/LICENSE new file mode 100644 index 0000000000..364b7731ca --- /dev/null +++ b/third_party/rust/typenum/LICENSE @@ -0,0 +1 @@ +MIT OR Apache-2.0
\ No newline at end of file diff --git a/third_party/rust/typenum/LICENSE-APACHE b/third_party/rust/typenum/LICENSE-APACHE new file mode 100644 index 0000000000..4bf355c3e0 --- /dev/null +++ b/third_party/rust/typenum/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2014 Paho Lurie-Gregg + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.
\ No newline at end of file diff --git a/third_party/rust/typenum/LICENSE-MIT b/third_party/rust/typenum/LICENSE-MIT new file mode 100644 index 0000000000..e567a4d280 --- /dev/null +++ b/third_party/rust/typenum/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Paho Lurie-Gregg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/rust/typenum/README.md b/third_party/rust/typenum/README.md new file mode 100644 index 0000000000..e8f12480c3 --- /dev/null +++ b/third_party/rust/typenum/README.md @@ -0,0 +1,67 @@ +[![crates.io](https://img.shields.io/crates/v/typenum.svg)](https://crates.io/crates/typenum) +[![Build Status](https://github.com/paholg/typenum/actions/workflows/check.yml/badge.svg)](https://github.com/paholg/typenum/actions/workflows/check.yml) + +Typenum +===== + +Typenum is a Rust library for type-level numbers evaluated at compile time. It +currently supports bits, unsigned integers, and signed integers. + +Typenum depends only on libcore, and so is suitable for use on any platform! + +For the full documentation, go [here](https://docs.rs/typenum). + +### Importing + +While `typenum` is divided into several modules, they are all re-exported +through the crate root, so you can import anything contained herein with `use +typenum::whatever;`, ignoring the crate structure. + +You may also find it useful to treat the `consts` module as a prelude, perfoming +a glob import. + +### Example + +Here is a trivial example of `typenum`'s use: + +```rust +use typenum::{Sum, Exp, Integer, N2, P3, P4}; + +type X = Sum<P3, P4>; +assert_eq!(<X as Integer>::to_i32(), 7); + +type Y = Exp<N2, P3>; +assert_eq!(<Y as Integer>::to_i32(), -8); +``` + +For a non-trivial example of its use, see one of the crates that depends on +it. The full list is +[here](https://crates.io/crates/typenum/reverse_dependencies). Of note are +[dimensioned](https://crates.io/crates/dimensioned/) which does compile-time +type checking for arbitrary unit systems and +[generic-array](https://crates.io/crates/generic-array/) which provides arrays +whose length you can generically refer to. + +### Error messages + + +Typenum's error messages aren't great, and can be difficult to parse. The good +news is that the fine folks at Auxon have written a tool to help with it. Please +take a look at [tnfilt](https://github.com/auxoncorp/tnfilt). + +### License + +Licensed under either of + + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license + ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/third_party/rust/typenum/build/generic_const_mappings.rs b/third_party/rust/typenum/build/generic_const_mappings.rs new file mode 100644 index 0000000000..20360e0416 --- /dev/null +++ b/third_party/rust/typenum/build/generic_const_mappings.rs @@ -0,0 +1,91 @@ +use super::*; + +pub fn emit_impls() -> ::std::io::Result<()> { + let out_dir = ::std::env::var("OUT_DIR").unwrap(); + let dest = ::std::path::Path::new(&out_dir).join("generic_const_mappings.rs"); + println!( + "cargo:rustc-env=TYPENUM_BUILD_GENERIC_CONSTS={}", + dest.display() + ); + let mut f = ::std::fs::File::create(&dest).unwrap(); + + #[allow(clippy::write_literal)] + write!(f, "{}", "\ +#[cfg(doc)] +use generic_const_mappings::*; + +/// Module with some `const`-generics-friendly definitions, to help bridge the gap +/// between those and `typenum` types. +/// +/// - It requires the `const-generics` crate feature to be enabled. +/// +/// The main type to use here is [`U`], although [`Const`] and [`ToUInt`] may be needed +/// in a generic context. +#[allow(warnings)] // script-generated code +pub mod generic_const_mappings { + use crate::*; + + /// The main mapping from a generic `const: usize` to a [`UInt`]: [`U<N>`] is expected to work like [`UN`]. + /// + /// - It requires the `const-generics` crate feature to be enabled. + /// + /// [`U<N>`]: `U` + /// [`UN`]: `U42` + /// + /// # Example + /// + /// ```rust + /// use typenum::*; + /// + /// assert_type_eq!(U<42>, U42); + /// ``` + /// + /// This can even be used in a generic `const N: usize` context, provided the + /// genericity is guarded by a `where` clause: + /// + /// ```rust + /// use typenum::*; + /// + /// struct MyStruct<const N: usize>; + /// + /// trait MyTrait { type AssocType; } + /// + /// impl<const N: usize> MyTrait + /// for MyStruct<N> + /// where + /// Const<N> : ToUInt, + /// { + /// type AssocType = U<N>; + /// } + /// + /// assert_type_eq!(<MyStruct<42> as MyTrait>::AssocType, U42); + /// ``` + pub type U<const N: usize> = <Const<N> as ToUInt>::Output; + + /// Used to allow the usage of [`U`] in a generic context. + pub struct Const<const N: usize>; + + /// Used to allow the usage of [`U`] in a generic context. + pub trait ToUInt { + /// The [`UN`][`crate::U42`] type corresponding to `Self = Const<N>`. + type Output; + } +\ + ")?; + + for uint in uints() { + write!( + f, + " + impl ToUInt for Const<{uint}> {{ + type Output = U{uint}; + }} +\ + ", + uint = uint, + )?; + } + write!(f, "}}")?; + f.flush()?; + Ok(()) +} diff --git a/third_party/rust/typenum/build/main.rs b/third_party/rust/typenum/build/main.rs new file mode 100644 index 0000000000..68a97af821 --- /dev/null +++ b/third_party/rust/typenum/build/main.rs @@ -0,0 +1,195 @@ +use std::env; +use std::fmt; +use std::fs::File; +use std::io::Write; +use std::path::Path; + +#[cfg(feature = "const-generics")] +mod generic_const_mappings; +mod op; +mod tests; + +pub enum UIntCode { + Term, + Zero(Box<UIntCode>), + One(Box<UIntCode>), +} + +pub enum IntCode { + Zero, + Pos(Box<UIntCode>), + Neg(Box<UIntCode>), +} + +impl fmt::Display for UIntCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + UIntCode::Term => write!(f, "UTerm"), + UIntCode::Zero(ref inner) => write!(f, "UInt<{}, B0>", inner), + UIntCode::One(ref inner) => write!(f, "UInt<{}, B1>", inner), + } + } +} + +impl fmt::Display for IntCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + IntCode::Zero => write!(f, "Z0"), + IntCode::Pos(ref inner) => write!(f, "PInt<{}>", inner), + IntCode::Neg(ref inner) => write!(f, "NInt<{}>", inner), + } + } +} + +pub fn gen_uint(u: u64) -> UIntCode { + let mut result = UIntCode::Term; + let mut x = 1u64 << 63; + while x > u { + x >>= 1 + } + while x > 0 { + result = if x & u > 0 { + UIntCode::One(Box::new(result)) + } else { + UIntCode::Zero(Box::new(result)) + }; + x >>= 1; + } + result +} + +pub fn gen_int(i: i64) -> IntCode { + use std::cmp::Ordering::{Equal, Greater, Less}; + + match i.cmp(&0) { + Greater => IntCode::Pos(Box::new(gen_uint(i as u64))), + Less => IntCode::Neg(Box::new(gen_uint(i.abs() as u64))), + Equal => IntCode::Zero, + } +} + +#[cfg_attr( + feature = "no_std", + deprecated( + since = "1.3.0", + note = "the `no_std` flag is no longer necessary and will be removed in the future" + ) +)] +pub fn no_std() {} + +const HIGHEST: u64 = 1024; +fn uints() -> impl Iterator<Item = u64> { + // Use hardcoded values to avoid issues with cross-compilation. + // See https://github.com/paholg/typenum/issues/162 + let first2: u32 = 11; // (highest as f64).log(2.0).round() as u32 + 1; + let first10: u32 = 4; // (highest as f64).log(10.0) as u32 + 1; + (0..(HIGHEST + 1)) + .chain((first2..64).map(|i| 2u64.pow(i))) + .chain((first10..20).map(|i| 10u64.pow(i))) +} + +// fixme: get a warning when testing without this +#[allow(dead_code)] +fn main() { + println!("cargo:rerun-if-changed=build/main.rs"); // Allow caching the generation if `src/*` files change. + + let out_dir = env::var("OUT_DIR").unwrap(); + let dest = Path::new(&out_dir).join("consts.rs"); + #[cfg(not(feature = "force_unix_path_separator"))] + println!("cargo:rustc-env=TYPENUM_BUILD_CONSTS={}", dest.display()); + + let mut f = File::create(&dest).unwrap(); + + no_std(); + + // Header stuff here! + write!( + f, + " +/** +Type aliases for many constants. + +This file is generated by typenum's build script. + +For unsigned integers, the format is `U` followed by the number. We define aliases for + +- Numbers 0 through {highest} +- Powers of 2 below `u64::MAX` +- Powers of 10 below `u64::MAX` + +These alias definitions look like this: + +```rust +use typenum::{{B0, B1, UInt, UTerm}}; + +# #[allow(dead_code)] +type U6 = UInt<UInt<UInt<UTerm, B1>, B1>, B0>; +``` + +For positive signed integers, the format is `P` followed by the number and for negative +signed integers it is `N` followed by the number. For the signed integer zero, we use +`Z0`. We define aliases for + +- Numbers -{highest} through {highest} +- Powers of 2 between `i64::MIN` and `i64::MAX` +- Powers of 10 between `i64::MIN` and `i64::MAX` + +These alias definitions look like this: + +```rust +use typenum::{{B0, B1, UInt, UTerm, PInt, NInt}}; + +# #[allow(dead_code)] +type P6 = PInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>>; +# #[allow(dead_code)] +type N6 = NInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>>; +``` + +# Example +```rust +# #[allow(unused_imports)] +use typenum::{{U0, U1, U2, U3, U4, U5, U6}}; +# #[allow(unused_imports)] +use typenum::{{N3, N2, N1, Z0, P1, P2, P3}}; +# #[allow(unused_imports)] +use typenum::{{U774, N17, N10000, P1024, P4096}}; +``` + +We also define the aliases `False` and `True` for `B0` and `B1`, respectively. +*/ +#[allow(missing_docs)] +pub mod consts {{ + use crate::uint::{{UInt, UTerm}}; + use crate::int::{{PInt, NInt}}; + + pub use crate::bit::{{B0, B1}}; + pub use crate::int::Z0; + + pub type True = B1; + pub type False = B0; +", + highest = HIGHEST, + ) + .unwrap(); + + for u in uints() { + writeln!(f, " pub type U{} = {};", u, gen_uint(u)).unwrap(); + if u <= ::std::i64::MAX as u64 && u != 0 { + let i = u as i64; + writeln!( + f, + " pub type P{i} = PInt<U{i}>; pub type N{i} = NInt<U{i}>;", + i = i + ) + .unwrap(); + } + } + write!(f, "}}").unwrap(); + + tests::build_tests().unwrap(); + + op::write_op_macro().unwrap(); + + #[cfg(feature = "const-generics")] + generic_const_mappings::emit_impls().unwrap(); +} diff --git a/third_party/rust/typenum/build/op.rs b/third_party/rust/typenum/build/op.rs new file mode 100644 index 0000000000..f567a88c8a --- /dev/null +++ b/third_party/rust/typenum/build/op.rs @@ -0,0 +1,560 @@ +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +enum OpType { + Operator, + Function, +} + +use self::OpType::*; + +struct Op { + token: &'static str, + operator: &'static str, + example: (&'static str, &'static str), + precedence: u8, + n_args: u8, + op_type: OpType, +} + +pub fn write_op_macro() -> ::std::io::Result<()> { + let out_dir = ::std::env::var("OUT_DIR").unwrap(); + let dest = ::std::path::Path::new(&out_dir).join("op.rs"); + #[cfg(not(feature = "force_unix_path_separator"))] + println!("cargo:rustc-env=TYPENUM_BUILD_OP={}", dest.display()); + let mut f = ::std::fs::File::create(&dest).unwrap(); + + // Operator precedence is taken from + // https://doc.rust-lang.org/reference.html#operator-precedence + // + // We choose 16 as the highest precedence (functions are set to 255 but it doesn't matter + // for them). We also only use operators that are left associative so we don't have to worry + // about that. + let ops = &[ + Op { + token: "*", + operator: "Prod", + example: ("P2 * P3", "P6"), + precedence: 16, + n_args: 2, + op_type: Operator, + }, + Op { + token: "/", + operator: "Quot", + example: ("P6 / P2", "P3"), + precedence: 16, + n_args: 2, + op_type: Operator, + }, + Op { + token: "%", + operator: "Mod", + example: ("P5 % P3", "P2"), + precedence: 16, + n_args: 2, + op_type: Operator, + }, + Op { + token: "+", + operator: "Sum", + example: ("P2 + P3", "P5"), + precedence: 15, + n_args: 2, + op_type: Operator, + }, + Op { + token: "-", + operator: "Diff", + example: ("P2 - P3", "N1"), + precedence: 15, + n_args: 2, + op_type: Operator, + }, + Op { + token: "<<", + operator: "Shleft", + example: ("U1 << U5", "U32"), + precedence: 14, + n_args: 2, + op_type: Operator, + }, + Op { + token: ">>", + operator: "Shright", + example: ("U32 >> U5", "U1"), + precedence: 14, + n_args: 2, + op_type: Operator, + }, + Op { + token: "&", + operator: "And", + example: ("U5 & U3", "U1"), + precedence: 13, + n_args: 2, + op_type: Operator, + }, + Op { + token: "^", + operator: "Xor", + example: ("U5 ^ U3", "U6"), + precedence: 12, + n_args: 2, + op_type: Operator, + }, + Op { + token: "|", + operator: "Or", + example: ("U5 | U3", "U7"), + precedence: 11, + n_args: 2, + op_type: Operator, + }, + Op { + token: "==", + operator: "Eq", + example: ("P5 == P3 + P2", "True"), + precedence: 10, + n_args: 2, + op_type: Operator, + }, + Op { + token: "!=", + operator: "NotEq", + example: ("P5 != P3 + P2", "False"), + precedence: 10, + n_args: 2, + op_type: Operator, + }, + Op { + token: "<=", + operator: "LeEq", + example: ("P6 <= P3 + P2", "False"), + precedence: 10, + n_args: 2, + op_type: Operator, + }, + Op { + token: ">=", + operator: "GrEq", + example: ("P6 >= P3 + P2", "True"), + precedence: 10, + n_args: 2, + op_type: Operator, + }, + Op { + token: "<", + operator: "Le", + example: ("P4 < P3 + P2", "True"), + precedence: 10, + n_args: 2, + op_type: Operator, + }, + Op { + token: ">", + operator: "Gr", + example: ("P5 < P3 + P2", "False"), + precedence: 10, + n_args: 2, + op_type: Operator, + }, + Op { + token: "cmp", + operator: "Compare", + example: ("cmp(P2, P3)", "Less"), + precedence: !0, + n_args: 2, + op_type: Function, + }, + Op { + token: "sqr", + operator: "Square", + example: ("sqr(P2)", "P4"), + precedence: !0, + n_args: 1, + op_type: Function, + }, + Op { + token: "sqrt", + operator: "Sqrt", + example: ("sqrt(U9)", "U3"), + precedence: !0, + n_args: 1, + op_type: Function, + }, + Op { + token: "abs", + operator: "AbsVal", + example: ("abs(N2)", "P2"), + precedence: !0, + n_args: 1, + op_type: Function, + }, + Op { + token: "cube", + operator: "Cube", + example: ("cube(P2)", "P8"), + precedence: !0, + n_args: 1, + op_type: Function, + }, + Op { + token: "pow", + operator: "Exp", + example: ("pow(P2, P3)", "P8"), + precedence: !0, + n_args: 2, + op_type: Function, + }, + Op { + token: "min", + operator: "Minimum", + example: ("min(P2, P3)", "P2"), + precedence: !0, + n_args: 2, + op_type: Function, + }, + Op { + token: "max", + operator: "Maximum", + example: ("max(P2, P3)", "P3"), + precedence: !0, + n_args: 2, + op_type: Function, + }, + Op { + token: "log2", + operator: "Log2", + example: ("log2(U9)", "U3"), + precedence: !0, + n_args: 1, + op_type: Function, + }, + Op { + token: "gcd", + operator: "Gcf", + example: ("gcd(U9, U21)", "U3"), + precedence: !0, + n_args: 2, + op_type: Function, + }, + ]; + + use std::io::Write; + write!( + f, + " +/** +Convenient type operations. + +Any types representing values must be able to be expressed as `ident`s. That means they need to be +in scope. + +For example, `P5` is okay, but `typenum::P5` is not. + +You may combine operators arbitrarily, although doing so excessively may require raising the +recursion limit. + +# Example +```rust +#![recursion_limit=\"128\"] +#[macro_use] extern crate typenum; +use typenum::consts::*; + +fn main() {{ + assert_type!( + op!(min((P1 - P2) * (N3 + N7), P5 * (P3 + P4)) == P10) + ); +}} +``` +Operators are evaluated based on the operator precedence outlined +[here](https://doc.rust-lang.org/reference.html#operator-precedence). + +The full list of supported operators and functions is as follows: + +{} + +They all expand to type aliases defined in the `operator_aliases` module. Here is an expanded list, +including examples: + +", + ops.iter() + .map(|op| format!("`{}`", op.token)) + .collect::<Vec<_>>() + .join(", ") + )?; + + //write!(f, "Token | Alias | Example\n ===|===|===\n")?; + + for op in ops.iter() { + write!( + f, + "---\nOperator `{token}`. Expands to `{operator}`. + +```rust +# #[macro_use] extern crate typenum; +# use typenum::*; +# fn main() {{ +assert_type_eq!(op!({ex0}), {ex1}); +# }} +```\n +", + token = op.token, + operator = op.operator, + ex0 = op.example.0, + ex1 = op.example.1 + )?; + } + + write!( + f, + "*/ +#[macro_export(local_inner_macros)] +macro_rules! op {{ + ($($tail:tt)*) => ( __op_internal__!($($tail)*) ); +}} + + #[doc(hidden)] + #[macro_export(local_inner_macros)] + macro_rules! __op_internal__ {{ +" + )?; + + // We first us the shunting-yard algorithm to produce our tokens in Polish notation. + // See: https://en.wikipedia.org/wiki/Shunting-yard_algorithm + + // Note: Due to macro asymmetry, "the top of the stack" refers to the first element, not the + // last + + // ----------------------------------------------------------------------------------------- + // Stage 1: There are tokens to be read: + + // ------- + // Case 1: Token is a function => Push it onto the stack: + for fun in ops.iter().filter(|f| f.op_type == Function) { + write!( + f, + " +(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {f_token} $($tail:tt)*) => ( + __op_internal__!(@stack[{f_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) +);", + f_token = fun.token, + f_op = fun.operator + )?; + } + + // ------- + // Case 2: Token is a comma => Until the top of the stack is a LParen, + // Pop operators from stack to queue + + // Base case: Top of stack is LParen, ditch comma and continue + write!( + f, + " +(@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => ( + __op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) +);" + )?; + // Recursive case: Not LParen, pop from stack to queue + write!( + f, + " +(@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => ( + __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: , $($tail)*) +);" + )?; + + // ------- + // Case 3: Token is an operator, o1: + for o1 in ops.iter().filter(|op| op.op_type == Operator) { + // If top of stack is operator o2 with o1.precedence <= o2.precedence, + // Then pop o2 off stack onto queue: + for o2 in ops + .iter() + .filter(|op| op.op_type == Operator) + .filter(|o2| o1.precedence <= o2.precedence) + { + write!( + f, + " +(@stack[{o2_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => ( + __op_internal__!(@stack[$($stack,)*] @queue[{o2_op}, $($queue,)*] @tail: {o1_token} $($tail)*) +);", + o2_op = o2.operator, + o1_token = o1.token + )?; + } + // Base case: push o1 onto stack + write!( + f, + " +(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => ( + __op_internal__!(@stack[{o1_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) +);", + o1_op = o1.operator, + o1_token = o1.token + )?; + } + + // ------- + // Case 4: Token is "(": push it onto stack as "LParen". Also convert the ")" to "RParen" to + // appease the macro gods: + write!( + f, + " +(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: ( $($stuff:tt)* ) $($tail:tt)* ) + => ( + __op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] + @tail: $($stuff)* RParen $($tail)*) +);" + )?; + + // ------- + // Case 5: Token is "RParen": + // 1. Pop from stack to queue until we see an "LParen", + // 2. Kill the "LParen", + // 3. If the top of the stack is a function, pop it onto the queue + // 2. Base case: + write!( + f, + " +(@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) => ( + __op_internal__!(@rp3 @stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) +);" + )?; + // 1. Recursive case: + write!( + f, + " +(@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) + => ( + __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: RParen $($tail)*) +);" + )?; + // 3. Check for function: + for fun in ops.iter().filter(|f| f.op_type == Function) { + write!( + f, + " +(@rp3 @stack[{fun_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => ( + __op_internal__!(@stack[$($stack,)*] @queue[{fun_op}, $($queue,)*] @tail: $($tail)*) +);", + fun_op = fun.operator + )?; + } + // 3. If no function found: + write!( + f, + " +(@rp3 @stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => ( + __op_internal__!(@stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) +);" + )?; + + // ------- + // Case 6: Token is a number: Push it onto the queue + write!( + f, + " +(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $num:ident $($tail:tt)*) => ( + __op_internal__!(@stack[$($stack,)*] @queue[$num, $($queue,)*] @tail: $($tail)*) +);" + )?; + + // ------- + // Case 7: Out of tokens: + // Base case: Stack empty: Start evaluating + write!( + f, + " +(@stack[] @queue[$($queue:ident,)*] @tail: ) => ( + __op_internal__!(@reverse[] @input: $($queue,)*) +);" + )?; + // Recursive case: Pop stack to queue + write!( + f, + " +(@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail:) => ( + __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: ) +);" + )?; + + // ----------------------------------------------------------------------------------------- + // Stage 2: Reverse so we have RPN + write!( + f, + " +(@reverse[$($revved:ident,)*] @input: $head:ident, $($tail:ident,)* ) => ( + __op_internal__!(@reverse[$head, $($revved,)*] @input: $($tail,)*) +);" + )?; + write!( + f, + " +(@reverse[$($revved:ident,)*] @input: ) => ( + __op_internal__!(@eval @stack[] @input[$($revved,)*]) +);" + )?; + + // ----------------------------------------------------------------------------------------- + // Stage 3: Evaluate in Reverse Polish Notation + // Operators / Operators with 2 args: + for op in ops.iter().filter(|op| op.n_args == 2) { + // Note: We have to switch $a and $b here, otherwise non-commutative functions are backwards + write!( + f, + " +(@eval @stack[$a:ty, $b:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => ( + __op_internal__!(@eval @stack[$crate::{op}<$b, $a>, $($stack,)*] @input[$($tail,)*]) +);", + op = op.operator + )?; + } + // Operators with 1 arg: + for op in ops.iter().filter(|op| op.n_args == 1) { + write!( + f, + " +(@eval @stack[$a:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => ( + __op_internal__!(@eval @stack[$crate::{op}<$a>, $($stack,)*] @input[$($tail,)*]) +);", + op = op.operator + )?; + } + + // Wasn't a function or operator, so must be a value => push onto stack + write!( + f, + " +(@eval @stack[$($stack:ty,)*] @input[$head:ident, $($tail:ident,)*]) => ( + __op_internal__!(@eval @stack[$head, $($stack,)*] @input[$($tail,)*]) +);" + )?; + + // No input left: + write!( + f, + " +(@eval @stack[$stack:ty,] @input[]) => ( + $stack +);" + )?; + + // ----------------------------------------------------------------------------------------- + // Stage 0: Get it started + write!( + f, + " +($($tail:tt)* ) => ( + __op_internal__!(@stack[] @queue[] @tail: $($tail)*) +);" + )?; + + write!( + f, + " +}}" + )?; + + Ok(()) +} diff --git a/third_party/rust/typenum/build/tests.rs b/third_party/rust/typenum/build/tests.rs new file mode 100644 index 0000000000..b0453a95fa --- /dev/null +++ b/third_party/rust/typenum/build/tests.rs @@ -0,0 +1,328 @@ +use std::{env, fmt, fs, io, path}; + +use super::{gen_int, gen_uint}; + +/// Computes the greatest common divisor of two integers. +fn gcdi(mut a: i64, mut b: i64) -> i64 { + a = a.abs(); + b = b.abs(); + + while a != 0 { + let tmp = b % a; + b = a; + a = tmp; + } + + b +} + +fn gcdu(mut a: u64, mut b: u64) -> u64 { + while a != 0 { + let tmp = b % a; + b = a; + a = tmp; + } + + b +} + +fn sign(i: i64) -> char { + use std::cmp::Ordering::*; + match i.cmp(&0) { + Greater => 'P', + Less => 'N', + Equal => '_', + } +} + +struct UIntTest { + a: u64, + op: &'static str, + b: Option<u64>, + r: u64, +} + +impl fmt::Display for UIntTest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.b { + Some(b) => write!( + f, + " +#[test] +#[allow(non_snake_case)] +fn test_{a}_{op}_{b}() {{ + type A = {gen_a}; + type B = {gen_b}; + type U{r} = {result}; + + #[allow(non_camel_case_types)] + type U{a}{op}U{b} = <<A as {op}<B>>::Output as Same<U{r}>>::Output; + + assert_eq!(<U{a}{op}U{b} as Unsigned>::to_u64(), <U{r} as Unsigned>::to_u64()); +}}", + gen_a = gen_uint(self.a), + gen_b = gen_uint(b), + r = self.r, + result = gen_uint(self.r), + a = self.a, + b = b, + op = self.op + ), + None => write!( + f, + " +#[test] +#[allow(non_snake_case)] +fn test_{a}_{op}() {{ + type A = {gen_a}; + type U{r} = {result}; + + #[allow(non_camel_case_types)] + type {op}U{a} = <<A as {op}>::Output as Same<U{r}>>::Output; + assert_eq!(<{op}U{a} as Unsigned>::to_u64(), <U{r} as Unsigned>::to_u64()); +}}", + gen_a = gen_uint(self.a), + r = self.r, + result = gen_uint(self.r), + a = self.a, + op = self.op + ), + } + } +} + +fn uint_binary_test(left: u64, operator: &'static str, right: u64, result: u64) -> UIntTest { + UIntTest { + a: left, + op: operator, + b: Option::Some(right), + r: result, + } +} + +// fn uint_unary_test(op: &'static str, a: u64, result: u64) -> UIntTest { +// UIntTest { a: a, op: op, b: Option::None, r: result } +// } + +struct IntBinaryTest { + a: i64, + op: &'static str, + b: i64, + r: i64, +} + +impl fmt::Display for IntBinaryTest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + " +#[test] +#[allow(non_snake_case)] +fn test_{sa}{a}_{op}_{sb}{b}() {{ + type A = {gen_a}; + type B = {gen_b}; + type {sr}{r} = {result}; + + #[allow(non_camel_case_types)] + type {sa}{a}{op}{sb}{b} = <<A as {op}<B>>::Output as Same<{sr}{r}>>::Output; + + assert_eq!(<{sa}{a}{op}{sb}{b} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64()); +}}", + gen_a = gen_int(self.a), + gen_b = gen_int(self.b), + r = self.r.abs(), + sr = sign(self.r), + result = gen_int(self.r), + a = self.a.abs(), + b = self.b.abs(), + sa = sign(self.a), + sb = sign(self.b), + op = self.op + ) + } +} + +fn int_binary_test(left: i64, operator: &'static str, right: i64, result: i64) -> IntBinaryTest { + IntBinaryTest { + a: left, + op: operator, + b: right, + r: result, + } +} + +struct IntUnaryTest { + op: &'static str, + a: i64, + r: i64, +} + +impl fmt::Display for IntUnaryTest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + " +#[test] +#[allow(non_snake_case)] +fn test_{sa}{a}_{op}() {{ + type A = {gen_a}; + type {sr}{r} = {result}; + + #[allow(non_camel_case_types)] + type {op}{sa}{a} = <<A as {op}>::Output as Same<{sr}{r}>>::Output; + assert_eq!(<{op}{sa}{a} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64()); +}}", + gen_a = gen_int(self.a), + r = self.r.abs(), + sr = sign(self.r), + result = gen_int(self.r), + a = self.a.abs(), + sa = sign(self.a), + op = self.op + ) + } +} + +fn int_unary_test(operator: &'static str, num: i64, result: i64) -> IntUnaryTest { + IntUnaryTest { + op: operator, + a: num, + r: result, + } +} + +fn uint_cmp_test(a: u64, b: u64) -> String { + format!( + " +#[test] +#[allow(non_snake_case)] +fn test_{a}_Cmp_{b}() {{ + type A = {gen_a}; + type B = {gen_b}; + + #[allow(non_camel_case_types)] + type U{a}CmpU{b} = <A as Cmp<B>>::Output; + assert_eq!(<U{a}CmpU{b} as Ord>::to_ordering(), Ordering::{result:?}); +}}", + a = a, + b = b, + gen_a = gen_uint(a), + gen_b = gen_uint(b), + result = a.cmp(&b) + ) +} + +fn int_cmp_test(a: i64, b: i64) -> String { + format!( + " +#[test] +#[allow(non_snake_case)] +fn test_{sa}{a}_Cmp_{sb}{b}() {{ + type A = {gen_a}; + type B = {gen_b}; + + #[allow(non_camel_case_types)] + type {sa}{a}Cmp{sb}{b} = <A as Cmp<B>>::Output; + assert_eq!(<{sa}{a}Cmp{sb}{b} as Ord>::to_ordering(), Ordering::{result:?}); +}}", + a = a.abs(), + b = b.abs(), + sa = sign(a), + sb = sign(b), + gen_a = gen_int(a), + gen_b = gen_int(b), + result = a.cmp(&b) + ) +} + +// Allow for rustc 1.22 compatibility. +#[allow(bare_trait_objects)] +pub fn build_tests() -> Result<(), Box<::std::error::Error>> { + // will test all permutations of number pairs up to this (and down to its opposite for ints) + let high: i64 = 5; + + let uints = (0u64..high as u64 + 1).flat_map(|a| (a..a + 1).cycle().zip(0..high as u64 + 1)); + let ints = (-high..high + 1).flat_map(|a| (a..a + 1).cycle().zip(-high..high + 1)); + + let out_dir = env::var("OUT_DIR")?; + let dest = path::Path::new(&out_dir).join("tests.rs"); + let f = fs::File::create(&dest)?; + let mut writer = io::BufWriter::new(&f); + use std::io::Write; + writer.write_all( + b" +extern crate typenum; + +use std::ops::*; +use std::cmp::Ordering; +use typenum::*; +", + )?; + use std::cmp; + // uint operators: + for (a, b) in uints { + write!(writer, "{}", uint_binary_test(a, "BitAnd", b, a & b))?; + write!(writer, "{}", uint_binary_test(a, "BitOr", b, a | b))?; + write!(writer, "{}", uint_binary_test(a, "BitXor", b, a ^ b))?; + write!(writer, "{}", uint_binary_test(a, "Shl", b, a << b))?; + write!(writer, "{}", uint_binary_test(a, "Shr", b, a >> b))?; + write!(writer, "{}", uint_binary_test(a, "Add", b, a + b))?; + write!(writer, "{}", uint_binary_test(a, "Min", b, cmp::min(a, b)))?; + write!(writer, "{}", uint_binary_test(a, "Max", b, cmp::max(a, b)))?; + write!(writer, "{}", uint_binary_test(a, "Gcd", b, gcdu(a, b)))?; + if a >= b { + write!(writer, "{}", uint_binary_test(a, "Sub", b, a - b))?; + } + write!(writer, "{}", uint_binary_test(a, "Mul", b, a * b))?; + if b != 0 { + write!(writer, "{}", uint_binary_test(a, "Div", b, a / b))?; + write!(writer, "{}", uint_binary_test(a, "Rem", b, a % b))?; + if a % b == 0 { + write!(writer, "{}", uint_binary_test(a, "PartialDiv", b, a / b))?; + } + } + write!(writer, "{}", uint_binary_test(a, "Pow", b, a.pow(b as u32)))?; + write!(writer, "{}", uint_cmp_test(a, b))?; + } + // int operators: + for (a, b) in ints { + write!(writer, "{}", int_binary_test(a, "Add", b, a + b))?; + write!(writer, "{}", int_binary_test(a, "Sub", b, a - b))?; + write!(writer, "{}", int_binary_test(a, "Mul", b, a * b))?; + write!(writer, "{}", int_binary_test(a, "Min", b, cmp::min(a, b)))?; + write!(writer, "{}", int_binary_test(a, "Max", b, cmp::max(a, b)))?; + write!(writer, "{}", int_binary_test(a, "Gcd", b, gcdi(a, b)))?; + if b != 0 { + write!(writer, "{}", int_binary_test(a, "Div", b, a / b))?; + write!(writer, "{}", int_binary_test(a, "Rem", b, a % b))?; + if a % b == 0 { + write!(writer, "{}", int_binary_test(a, "PartialDiv", b, a / b))?; + } + } + if b >= 0 || a.abs() == 1 { + let result = if b < 0 { + if a == 1 { + a + } else if a == -1 { + a.pow((-b) as u32) + } else { + unreachable!() + } + } else { + a.pow(b as u32) + }; + write!(writer, "{}", int_binary_test(a, "Pow", b, result))?; + } + write!(writer, "{}", int_cmp_test(a, b))?; + } + + // int unary operators: + for n in -high..high + 1 { + write!(writer, "{}", int_unary_test("Neg", n, -n))?; + write!(writer, "{}", int_unary_test("Abs", n, n.abs()))?; + } + + writer.flush()?; + + Ok(()) +} diff --git a/third_party/rust/typenum/clippy.toml b/third_party/rust/typenum/clippy.toml new file mode 100644 index 0000000000..719c94d5dc --- /dev/null +++ b/third_party/rust/typenum/clippy.toml @@ -0,0 +1 @@ +cognitive-complexity-threshold=35 diff --git a/third_party/rust/typenum/rustfmt.toml b/third_party/rust/typenum/rustfmt.toml new file mode 100644 index 0000000000..16bdde911a --- /dev/null +++ b/third_party/rust/typenum/rustfmt.toml @@ -0,0 +1 @@ +format_code_in_doc_comments = true diff --git a/third_party/rust/typenum/src/array.rs b/third_party/rust/typenum/src/array.rs new file mode 100644 index 0000000000..08eedbe6dd --- /dev/null +++ b/third_party/rust/typenum/src/array.rs @@ -0,0 +1,340 @@ +//! A type-level array of type-level numbers. +//! +//! It is not very featureful right now, and should be considered a work in progress. + +use core::ops::{Add, Div, Mul, Sub}; + +use super::*; + +/// The terminating type for type arrays. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct ATerm; + +impl TypeArray for ATerm {} + +/// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its +/// values can be more than bits, and it is designed to act as an array. So you can only add two if +/// they have the same number of elements, for example. +/// +/// This array is only really designed to contain `Integer` types. If you use it with others, you +/// may find it lacking functionality. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct TArr<V, A> { + first: V, + rest: A, +} + +impl<V, A> TypeArray for TArr<V, A> {} + +/// Create a new type-level arrray. Only usable on Rust 1.13.0 or newer. +/// +/// There's not a whole lot you can do with it right now. +/// +/// # Example +/// ```rust +/// #[macro_use] +/// extern crate typenum; +/// use typenum::consts::*; +/// +/// type Array = tarr![P3, N4, Z0, P38]; +/// # fn main() { let _: Array; } +#[macro_export] +macro_rules! tarr { + () => ( $crate::ATerm ); + ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> ); + ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> ); + ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> ); + ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> ); +} + +// --------------------------------------------------------------------------------------- +// Length + +/// Length of `ATerm` by itself is 0 +impl Len for ATerm { + type Output = U0; + #[inline] + fn len(&self) -> Self::Output { + UTerm + } +} + +/// Size of a `TypeArray` +impl<V, A> Len for TArr<V, A> +where + A: Len, + Length<A>: Add<B1>, + Sum<Length<A>, B1>: Unsigned, +{ + type Output = Add1<Length<A>>; + #[inline] + fn len(&self) -> Self::Output { + self.rest.len() + B1 + } +} + +// --------------------------------------------------------------------------------------- +// Add arrays +// Note that two arrays are only addable if they are the same length. + +impl Add<ATerm> for ATerm { + type Output = ATerm; + #[inline] + fn add(self, _: ATerm) -> Self::Output { + ATerm + } +} + +impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al> +where + Al: Add<Ar>, + Vl: Add<Vr>, +{ + type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>; + #[inline] + fn add(self, rhs: TArr<Vr, Ar>) -> Self::Output { + TArr { + first: self.first + rhs.first, + rest: self.rest + rhs.rest, + } + } +} + +// --------------------------------------------------------------------------------------- +// Subtract arrays +// Note that two arrays are only subtractable if they are the same length. + +impl Sub<ATerm> for ATerm { + type Output = ATerm; + #[inline] + fn sub(self, _: ATerm) -> Self::Output { + ATerm + } +} + +impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al> +where + Vl: Sub<Vr>, + Al: Sub<Ar>, +{ + type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>; + #[inline] + fn sub(self, rhs: TArr<Vr, Ar>) -> Self::Output { + TArr { + first: self.first - rhs.first, + rest: self.rest - rhs.rest, + } + } +} + +// --------------------------------------------------------------------------------------- +// Multiply an array by a scalar + +impl<Rhs> Mul<Rhs> for ATerm { + type Output = ATerm; + #[inline] + fn mul(self, _: Rhs) -> Self::Output { + ATerm + } +} + +impl<V, A, Rhs> Mul<Rhs> for TArr<V, A> +where + V: Mul<Rhs>, + A: Mul<Rhs>, + Rhs: Copy, +{ + type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>; + #[inline] + fn mul(self, rhs: Rhs) -> Self::Output { + TArr { + first: self.first * rhs, + rest: self.rest * rhs, + } + } +} + +impl Mul<ATerm> for Z0 { + type Output = ATerm; + #[inline] + fn mul(self, _: ATerm) -> Self::Output { + ATerm + } +} + +impl<U> Mul<ATerm> for PInt<U> +where + U: Unsigned + NonZero, +{ + type Output = ATerm; + #[inline] + fn mul(self, _: ATerm) -> Self::Output { + ATerm + } +} + +impl<U> Mul<ATerm> for NInt<U> +where + U: Unsigned + NonZero, +{ + type Output = ATerm; + #[inline] + fn mul(self, _: ATerm) -> Self::Output { + ATerm + } +} + +impl<V, A> Mul<TArr<V, A>> for Z0 +where + Z0: Mul<A>, +{ + type Output = TArr<Z0, Prod<Z0, A>>; + #[inline] + fn mul(self, rhs: TArr<V, A>) -> Self::Output { + TArr { + first: Z0, + rest: self * rhs.rest, + } + } +} + +impl<V, A, U> Mul<TArr<V, A>> for PInt<U> +where + U: Unsigned + NonZero, + PInt<U>: Mul<A> + Mul<V>, +{ + type Output = TArr<Prod<PInt<U>, V>, Prod<PInt<U>, A>>; + #[inline] + fn mul(self, rhs: TArr<V, A>) -> Self::Output { + TArr { + first: self * rhs.first, + rest: self * rhs.rest, + } + } +} + +impl<V, A, U> Mul<TArr<V, A>> for NInt<U> +where + U: Unsigned + NonZero, + NInt<U>: Mul<A> + Mul<V>, +{ + type Output = TArr<Prod<NInt<U>, V>, Prod<NInt<U>, A>>; + #[inline] + fn mul(self, rhs: TArr<V, A>) -> Self::Output { + TArr { + first: self * rhs.first, + rest: self * rhs.rest, + } + } +} + +// --------------------------------------------------------------------------------------- +// Divide an array by a scalar + +impl<Rhs> Div<Rhs> for ATerm { + type Output = ATerm; + #[inline] + fn div(self, _: Rhs) -> Self::Output { + ATerm + } +} + +impl<V, A, Rhs> Div<Rhs> for TArr<V, A> +where + V: Div<Rhs>, + A: Div<Rhs>, + Rhs: Copy, +{ + type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>; + #[inline] + fn div(self, rhs: Rhs) -> Self::Output { + TArr { + first: self.first / rhs, + rest: self.rest / rhs, + } + } +} + +// --------------------------------------------------------------------------------------- +// Partial Divide an array by a scalar + +impl<Rhs> PartialDiv<Rhs> for ATerm { + type Output = ATerm; + #[inline] + fn partial_div(self, _: Rhs) -> Self::Output { + ATerm + } +} + +impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A> +where + V: PartialDiv<Rhs>, + A: PartialDiv<Rhs>, + Rhs: Copy, +{ + type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>; + #[inline] + fn partial_div(self, rhs: Rhs) -> Self::Output { + TArr { + first: self.first.partial_div(rhs), + rest: self.rest.partial_div(rhs), + } + } +} + +// --------------------------------------------------------------------------------------- +// Modulo an array by a scalar +use core::ops::Rem; + +impl<Rhs> Rem<Rhs> for ATerm { + type Output = ATerm; + #[inline] + fn rem(self, _: Rhs) -> Self::Output { + ATerm + } +} + +impl<V, A, Rhs> Rem<Rhs> for TArr<V, A> +where + V: Rem<Rhs>, + A: Rem<Rhs>, + Rhs: Copy, +{ + type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>; + #[inline] + fn rem(self, rhs: Rhs) -> Self::Output { + TArr { + first: self.first % rhs, + rest: self.rest % rhs, + } + } +} + +// --------------------------------------------------------------------------------------- +// Negate an array +use core::ops::Neg; + +impl Neg for ATerm { + type Output = ATerm; + #[inline] + fn neg(self) -> Self::Output { + ATerm + } +} + +impl<V, A> Neg for TArr<V, A> +where + V: Neg, + A: Neg, +{ + type Output = TArr<Negate<V>, Negate<A>>; + #[inline] + fn neg(self) -> Self::Output { + TArr { + first: -self.first, + rest: -self.rest, + } + } +} diff --git a/third_party/rust/typenum/src/bit.rs b/third_party/rust/typenum/src/bit.rs new file mode 100644 index 0000000000..4a098fe842 --- /dev/null +++ b/third_party/rust/typenum/src/bit.rs @@ -0,0 +1,337 @@ +//! Type-level bits. +//! +//! These are rather simple and are used as the building blocks of the +//! other number types in this crate. +//! +//! +//! **Type operators** implemented: +//! +//! - From `core::ops`: `BitAnd`, `BitOr`, `BitXor`, and `Not`. +//! - From `typenum`: `Same` and `Cmp`. + +use crate::{private::InternalMarker, Cmp, Equal, Greater, Less, NonZero, PowerOfTwo, Zero}; +use core::ops::{BitAnd, BitOr, BitXor, Not}; + +pub use crate::marker_traits::Bit; + +/// The type-level bit 0. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct B0; + +impl B0 { + /// Instantiates a singleton representing this bit. + #[inline] + pub fn new() -> B0 { + B0 + } +} + +/// The type-level bit 1. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct B1; + +impl B1 { + /// Instantiates a singleton representing this bit. + #[inline] + pub fn new() -> B1 { + B1 + } +} + +impl Bit for B0 { + const U8: u8 = 0; + const BOOL: bool = false; + + #[inline] + fn new() -> Self { + Self + } + #[inline] + fn to_u8() -> u8 { + 0 + } + #[inline] + fn to_bool() -> bool { + false + } +} + +impl Bit for B1 { + const U8: u8 = 1; + const BOOL: bool = true; + + #[inline] + fn new() -> Self { + Self + } + #[inline] + fn to_u8() -> u8 { + 1 + } + #[inline] + fn to_bool() -> bool { + true + } +} + +impl Zero for B0 {} +impl NonZero for B1 {} +impl PowerOfTwo for B1 {} + +/// Not of 0 (!0 = 1) +impl Not for B0 { + type Output = B1; + #[inline] + fn not(self) -> Self::Output { + B1 + } +} +/// Not of 1 (!1 = 0) +impl Not for B1 { + type Output = B0; + #[inline] + fn not(self) -> Self::Output { + B0 + } +} + +/// And with 0 ( 0 & B = 0) +impl<Rhs: Bit> BitAnd<Rhs> for B0 { + type Output = B0; + #[inline] + fn bitand(self, _: Rhs) -> Self::Output { + B0 + } +} + +/// And with 1 ( 1 & 0 = 0) +impl BitAnd<B0> for B1 { + type Output = B0; + #[inline] + fn bitand(self, _: B0) -> Self::Output { + B0 + } +} + +/// And with 1 ( 1 & 1 = 1) +impl BitAnd<B1> for B1 { + type Output = B1; + #[inline] + fn bitand(self, _: B1) -> Self::Output { + B1 + } +} + +/// Or with 0 ( 0 | 0 = 0) +impl BitOr<B0> for B0 { + type Output = B0; + #[inline] + fn bitor(self, _: B0) -> Self::Output { + B0 + } +} + +/// Or with 0 ( 0 | 1 = 1) +impl BitOr<B1> for B0 { + type Output = B1; + #[inline] + fn bitor(self, _: B1) -> Self::Output { + B1 + } +} + +/// Or with 1 ( 1 | B = 1) +impl<Rhs: Bit> BitOr<Rhs> for B1 { + type Output = B1; + #[inline] + fn bitor(self, _: Rhs) -> Self::Output { + B1 + } +} + +/// Xor between 0 and 0 ( 0 ^ 0 = 0) +impl BitXor<B0> for B0 { + type Output = B0; + #[inline] + fn bitxor(self, _: B0) -> Self::Output { + B0 + } +} +/// Xor between 1 and 0 ( 1 ^ 0 = 1) +impl BitXor<B0> for B1 { + type Output = B1; + #[inline] + fn bitxor(self, _: B0) -> Self::Output { + B1 + } +} +/// Xor between 0 and 1 ( 0 ^ 1 = 1) +impl BitXor<B1> for B0 { + type Output = B1; + #[inline] + fn bitxor(self, _: B1) -> Self::Output { + B1 + } +} +/// Xor between 1 and 1 ( 1 ^ 1 = 0) +impl BitXor<B1> for B1 { + type Output = B0; + #[inline] + fn bitxor(self, _: B1) -> Self::Output { + B0 + } +} + +#[cfg(tests)] +mod tests { + // macro for testing operation results. Uses `Same` to ensure the types are equal and + // not just the values they evaluate to. + macro_rules! test_bit_op { + ($op:ident $Lhs:ident = $Answer:ident) => {{ + type Test = <<$Lhs as $op>::Output as ::Same<$Answer>>::Output; + assert_eq!(<$Answer as Bit>::to_u8(), <Test as Bit>::to_u8()); + }}; + ($Lhs:ident $op:ident $Rhs:ident = $Answer:ident) => {{ + type Test = <<$Lhs as $op<$Rhs>>::Output as ::Same<$Answer>>::Output; + assert_eq!(<$Answer as Bit>::to_u8(), <Test as Bit>::to_u8()); + }}; + } + + #[test] + fn bit_operations() { + test_bit_op!(Not B0 = B1); + test_bit_op!(Not B1 = B0); + + test_bit_op!(B0 BitAnd B0 = B0); + test_bit_op!(B0 BitAnd B1 = B0); + test_bit_op!(B1 BitAnd B0 = B0); + test_bit_op!(B1 BitAnd B1 = B1); + + test_bit_op!(B0 BitOr B0 = B0); + test_bit_op!(B0 BitOr B1 = B1); + test_bit_op!(B1 BitOr B0 = B1); + test_bit_op!(B1 BitOr B1 = B1); + + test_bit_op!(B0 BitXor B0 = B0); + test_bit_op!(B0 BitXor B1 = B1); + test_bit_op!(B1 BitXor B0 = B1); + test_bit_op!(B1 BitXor B1 = B0); + } +} + +impl Cmp<B0> for B0 { + type Output = Equal; + + #[inline] + fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output { + Equal + } +} + +impl Cmp<B1> for B0 { + type Output = Less; + + #[inline] + fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output { + Less + } +} + +impl Cmp<B0> for B1 { + type Output = Greater; + + #[inline] + fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output { + Greater + } +} + +impl Cmp<B1> for B1 { + type Output = Equal; + + #[inline] + fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output { + Equal + } +} + +use crate::Min; +impl Min<B0> for B0 { + type Output = B0; + #[inline] + fn min(self, _: B0) -> B0 { + self + } +} +impl Min<B1> for B0 { + type Output = B0; + #[inline] + fn min(self, _: B1) -> B0 { + self + } +} +impl Min<B0> for B1 { + type Output = B0; + #[inline] + fn min(self, rhs: B0) -> B0 { + rhs + } +} +impl Min<B1> for B1 { + type Output = B1; + #[inline] + fn min(self, _: B1) -> B1 { + self + } +} + +use crate::Max; +impl Max<B0> for B0 { + type Output = B0; + #[inline] + fn max(self, _: B0) -> B0 { + self + } +} +impl Max<B1> for B0 { + type Output = B1; + #[inline] + fn max(self, rhs: B1) -> B1 { + rhs + } +} +impl Max<B0> for B1 { + type Output = B1; + #[inline] + fn max(self, _: B0) -> B1 { + self + } +} +impl Max<B1> for B1 { + type Output = B1; + #[inline] + fn max(self, _: B1) -> B1 { + self + } +} + +#[cfg(test)] +mod tests { + #[test] + fn bit_creation() { + { + use crate::{B0, B1}; + let _: B0 = B0::new(); + let _: B1 = B1::new(); + } + + { + use crate::{Bit, B0, B1}; + + let _: B0 = <B0 as Bit>::new(); + let _: B1 = <B1 as Bit>::new(); + } + } +} diff --git a/third_party/rust/typenum/src/int.rs b/third_party/rust/typenum/src/int.rs new file mode 100644 index 0000000000..1f6eaebc14 --- /dev/null +++ b/third_party/rust/typenum/src/int.rs @@ -0,0 +1,1401 @@ +//! Type-level signed integers. +//! +//! +//! Type **operators** implemented: +//! +//! From `core::ops`: `Add`, `Sub`, `Mul`, `Div`, and `Rem`. +//! From `typenum`: `Same`, `Cmp`, and `Pow`. +//! +//! Rather than directly using the structs defined in this module, it is recommended that +//! you import and use the relevant aliases from the [consts](../consts/index.html) module. +//! +//! Note that operators that work on the underlying structure of the number are +//! intentionally not implemented. This is because this implementation of signed integers +//! does *not* use twos-complement, and implementing them would require making arbitrary +//! choices, causing the results of such operators to be difficult to reason about. +//! +//! # Example +//! ```rust +//! use std::ops::{Add, Div, Mul, Rem, Sub}; +//! use typenum::{Integer, N3, P2}; +//! +//! assert_eq!(<N3 as Add<P2>>::Output::to_i32(), -1); +//! assert_eq!(<N3 as Sub<P2>>::Output::to_i32(), -5); +//! assert_eq!(<N3 as Mul<P2>>::Output::to_i32(), -6); +//! assert_eq!(<N3 as Div<P2>>::Output::to_i32(), -1); +//! assert_eq!(<N3 as Rem<P2>>::Output::to_i32(), -1); +//! ``` + +pub use crate::marker_traits::Integer; +use crate::{ + bit::{Bit, B0, B1}, + consts::{N1, P1, U0, U1}, + private::{Internal, InternalMarker, PrivateDivInt, PrivateIntegerAdd, PrivateRem}, + uint::{UInt, Unsigned}, + Cmp, Equal, Greater, Less, NonZero, Pow, PowerOfTwo, ToInt, Zero, +}; +use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; + +/// Type-level signed integers with positive sign. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct PInt<U: Unsigned + NonZero> { + pub(crate) n: U, +} + +/// Type-level signed integers with negative sign. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct NInt<U: Unsigned + NonZero> { + pub(crate) n: U, +} + +impl<U: Unsigned + NonZero> PInt<U> { + /// Instantiates a singleton representing this strictly positive integer. + #[inline] + pub fn new() -> PInt<U> { + PInt::default() + } +} + +impl<U: Unsigned + NonZero> NInt<U> { + /// Instantiates a singleton representing this strictly negative integer. + #[inline] + pub fn new() -> NInt<U> { + NInt::default() + } +} + +/// The type-level signed integer 0. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct Z0; + +impl Z0 { + /// Instantiates a singleton representing the integer 0. + #[inline] + pub fn new() -> Z0 { + Z0 + } +} + +impl<U: Unsigned + NonZero> NonZero for PInt<U> {} +impl<U: Unsigned + NonZero> NonZero for NInt<U> {} +impl Zero for Z0 {} + +impl<U: Unsigned + NonZero + PowerOfTwo> PowerOfTwo for PInt<U> {} + +impl Integer for Z0 { + const I8: i8 = 0; + const I16: i16 = 0; + const I32: i32 = 0; + const I64: i64 = 0; + #[cfg(feature = "i128")] + const I128: i128 = 0; + const ISIZE: isize = 0; + + #[inline] + fn to_i8() -> i8 { + 0 + } + #[inline] + fn to_i16() -> i16 { + 0 + } + #[inline] + fn to_i32() -> i32 { + 0 + } + #[inline] + fn to_i64() -> i64 { + 0 + } + #[cfg(feature = "i128")] + #[inline] + fn to_i128() -> i128 { + 0 + } + #[inline] + fn to_isize() -> isize { + 0 + } +} + +impl<U: Unsigned + NonZero> Integer for PInt<U> { + const I8: i8 = U::I8; + const I16: i16 = U::I16; + const I32: i32 = U::I32; + const I64: i64 = U::I64; + #[cfg(feature = "i128")] + const I128: i128 = U::I128; + const ISIZE: isize = U::ISIZE; + + #[inline] + fn to_i8() -> i8 { + <U as Unsigned>::to_i8() + } + #[inline] + fn to_i16() -> i16 { + <U as Unsigned>::to_i16() + } + #[inline] + fn to_i32() -> i32 { + <U as Unsigned>::to_i32() + } + #[inline] + fn to_i64() -> i64 { + <U as Unsigned>::to_i64() + } + #[cfg(feature = "i128")] + #[inline] + fn to_i128() -> i128 { + <U as Unsigned>::to_i128() + } + #[inline] + fn to_isize() -> isize { + <U as Unsigned>::to_isize() + } +} + +// Simply negating the result of e.g. `U::I8` will result in overflow for `std::i8::MIN`. Instead, +// we use the fact that `U: NonZero` by subtracting one from the `U::U8` before negating. +impl<U: Unsigned + NonZero> Integer for NInt<U> { + const I8: i8 = -((U::U8 - 1) as i8) - 1; + const I16: i16 = -((U::U16 - 1) as i16) - 1; + const I32: i32 = -((U::U32 - 1) as i32) - 1; + const I64: i64 = -((U::U64 - 1) as i64) - 1; + #[cfg(feature = "i128")] + const I128: i128 = -((U::U128 - 1) as i128) - 1; + const ISIZE: isize = -((U::USIZE - 1) as isize) - 1; + + #[inline] + fn to_i8() -> i8 { + Self::I8 + } + #[inline] + fn to_i16() -> i16 { + Self::I16 + } + #[inline] + fn to_i32() -> i32 { + Self::I32 + } + #[inline] + fn to_i64() -> i64 { + Self::I64 + } + #[cfg(feature = "i128")] + #[inline] + fn to_i128() -> i128 { + Self::I128 + } + #[inline] + fn to_isize() -> isize { + Self::ISIZE + } +} + +// --------------------------------------------------------------------------------------- +// Neg + +/// `-Z0 = Z0` +impl Neg for Z0 { + type Output = Z0; + #[inline] + fn neg(self) -> Self::Output { + Z0 + } +} + +/// `-PInt = NInt` +impl<U: Unsigned + NonZero> Neg for PInt<U> { + type Output = NInt<U>; + #[inline] + fn neg(self) -> Self::Output { + NInt::new() + } +} + +/// `-NInt = PInt` +impl<U: Unsigned + NonZero> Neg for NInt<U> { + type Output = PInt<U>; + #[inline] + fn neg(self) -> Self::Output { + PInt::new() + } +} + +// --------------------------------------------------------------------------------------- +// Add + +/// `Z0 + I = I` +impl<I: Integer> Add<I> for Z0 { + type Output = I; + #[inline] + fn add(self, rhs: I) -> Self::Output { + rhs + } +} + +/// `PInt + Z0 = PInt` +impl<U: Unsigned + NonZero> Add<Z0> for PInt<U> { + type Output = PInt<U>; + #[inline] + fn add(self, _: Z0) -> Self::Output { + PInt::new() + } +} + +/// `NInt + Z0 = NInt` +impl<U: Unsigned + NonZero> Add<Z0> for NInt<U> { + type Output = NInt<U>; + #[inline] + fn add(self, _: Z0) -> Self::Output { + NInt::new() + } +} + +/// `P(Ul) + P(Ur) = P(Ul + Ur)` +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<PInt<Ur>> for PInt<Ul> +where + Ul: Add<Ur>, + <Ul as Add<Ur>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<Ul as Add<Ur>>::Output>; + #[inline] + fn add(self, _: PInt<Ur>) -> Self::Output { + PInt::new() + } +} + +/// `N(Ul) + N(Ur) = N(Ul + Ur)` +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<NInt<Ur>> for NInt<Ul> +where + Ul: Add<Ur>, + <Ul as Add<Ur>>::Output: Unsigned + NonZero, +{ + type Output = NInt<<Ul as Add<Ur>>::Output>; + #[inline] + fn add(self, _: NInt<Ur>) -> Self::Output { + NInt::new() + } +} + +/// `P(Ul) + N(Ur)`: We resolve this with our `PrivateAdd` +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<NInt<Ur>> for PInt<Ul> +where + Ul: Cmp<Ur> + PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>, +{ + type Output = <Ul as PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>>::Output; + #[inline] + fn add(self, rhs: NInt<Ur>) -> Self::Output { + let lhs = self.n; + let rhs = rhs.n; + let lhs_cmp_rhs = lhs.compare::<Internal>(&rhs); + lhs.private_integer_add(lhs_cmp_rhs, rhs) + } +} + +/// `N(Ul) + P(Ur)`: We resolve this with our `PrivateAdd` +// We just do the same thing as above, swapping Lhs and Rhs +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<PInt<Ur>> for NInt<Ul> +where + Ur: Cmp<Ul> + PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>, +{ + type Output = <Ur as PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>>::Output; + #[inline] + fn add(self, rhs: PInt<Ur>) -> Self::Output { + let lhs = self.n; + let rhs = rhs.n; + let rhs_cmp_lhs = rhs.compare::<Internal>(&lhs); + rhs.private_integer_add(rhs_cmp_lhs, lhs) + } +} + +/// `P + N = 0` where `P == N` +impl<N: Unsigned, P: Unsigned> PrivateIntegerAdd<Equal, N> for P { + type Output = Z0; + + #[inline] + fn private_integer_add(self, _: Equal, _: N) -> Self::Output { + Z0 + } +} + +/// `P + N = Positive` where `P > N` +impl<N: Unsigned, P: Unsigned> PrivateIntegerAdd<Greater, N> for P +where + P: Sub<N>, + <P as Sub<N>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<P as Sub<N>>::Output>; + + #[inline] + fn private_integer_add(self, _: Greater, n: N) -> Self::Output { + PInt { n: self - n } + } +} + +/// `P + N = Negative` where `P < N` +impl<N: Unsigned, P: Unsigned> PrivateIntegerAdd<Less, N> for P +where + N: Sub<P>, + <N as Sub<P>>::Output: Unsigned + NonZero, +{ + type Output = NInt<<N as Sub<P>>::Output>; + + #[inline] + fn private_integer_add(self, _: Less, n: N) -> Self::Output { + NInt { n: n - self } + } +} + +// --------------------------------------------------------------------------------------- +// Sub + +/// `Z0 - Z0 = Z0` +impl Sub<Z0> for Z0 { + type Output = Z0; + #[inline] + fn sub(self, _: Z0) -> Self::Output { + Z0 + } +} + +/// `Z0 - P = N` +impl<U: Unsigned + NonZero> Sub<PInt<U>> for Z0 { + type Output = NInt<U>; + #[inline] + fn sub(self, _: PInt<U>) -> Self::Output { + NInt::new() + } +} + +/// `Z0 - N = P` +impl<U: Unsigned + NonZero> Sub<NInt<U>> for Z0 { + type Output = PInt<U>; + #[inline] + fn sub(self, _: NInt<U>) -> Self::Output { + PInt::new() + } +} + +/// `PInt - Z0 = PInt` +impl<U: Unsigned + NonZero> Sub<Z0> for PInt<U> { + type Output = PInt<U>; + #[inline] + fn sub(self, _: Z0) -> Self::Output { + PInt::new() + } +} + +/// `NInt - Z0 = NInt` +impl<U: Unsigned + NonZero> Sub<Z0> for NInt<U> { + type Output = NInt<U>; + #[inline] + fn sub(self, _: Z0) -> Self::Output { + NInt::new() + } +} + +/// `P(Ul) - N(Ur) = P(Ul + Ur)` +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<NInt<Ur>> for PInt<Ul> +where + Ul: Add<Ur>, + <Ul as Add<Ur>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<Ul as Add<Ur>>::Output>; + #[inline] + fn sub(self, _: NInt<Ur>) -> Self::Output { + PInt::new() + } +} + +/// `N(Ul) - P(Ur) = N(Ul + Ur)` +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<PInt<Ur>> for NInt<Ul> +where + Ul: Add<Ur>, + <Ul as Add<Ur>>::Output: Unsigned + NonZero, +{ + type Output = NInt<<Ul as Add<Ur>>::Output>; + #[inline] + fn sub(self, _: PInt<Ur>) -> Self::Output { + NInt::new() + } +} + +/// `P(Ul) - P(Ur)`: We resolve this with our `PrivateAdd` +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<PInt<Ur>> for PInt<Ul> +where + Ul: Cmp<Ur> + PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>, +{ + type Output = <Ul as PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>>::Output; + #[inline] + fn sub(self, rhs: PInt<Ur>) -> Self::Output { + let lhs = self.n; + let rhs = rhs.n; + let lhs_cmp_rhs = lhs.compare::<Internal>(&rhs); + lhs.private_integer_add(lhs_cmp_rhs, rhs) + } +} + +/// `N(Ul) - N(Ur)`: We resolve this with our `PrivateAdd` +// We just do the same thing as above, swapping Lhs and Rhs +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<NInt<Ur>> for NInt<Ul> +where + Ur: Cmp<Ul> + PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>, +{ + type Output = <Ur as PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>>::Output; + #[inline] + fn sub(self, rhs: NInt<Ur>) -> Self::Output { + let lhs = self.n; + let rhs = rhs.n; + let rhs_cmp_lhs = rhs.compare::<Internal>(&lhs); + rhs.private_integer_add(rhs_cmp_lhs, lhs) + } +} + +// --------------------------------------------------------------------------------------- +// Mul + +/// `Z0 * I = Z0` +impl<I: Integer> Mul<I> for Z0 { + type Output = Z0; + #[inline] + fn mul(self, _: I) -> Self::Output { + Z0 + } +} + +/// `P * Z0 = Z0` +impl<U: Unsigned + NonZero> Mul<Z0> for PInt<U> { + type Output = Z0; + #[inline] + fn mul(self, _: Z0) -> Self::Output { + Z0 + } +} + +/// `N * Z0 = Z0` +impl<U: Unsigned + NonZero> Mul<Z0> for NInt<U> { + type Output = Z0; + #[inline] + fn mul(self, _: Z0) -> Self::Output { + Z0 + } +} + +/// P(Ul) * P(Ur) = P(Ul * Ur) +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<PInt<Ur>> for PInt<Ul> +where + Ul: Mul<Ur>, + <Ul as Mul<Ur>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<Ul as Mul<Ur>>::Output>; + #[inline] + fn mul(self, _: PInt<Ur>) -> Self::Output { + PInt::new() + } +} + +/// N(Ul) * N(Ur) = P(Ul * Ur) +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<NInt<Ur>> for NInt<Ul> +where + Ul: Mul<Ur>, + <Ul as Mul<Ur>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<Ul as Mul<Ur>>::Output>; + #[inline] + fn mul(self, _: NInt<Ur>) -> Self::Output { + PInt::new() + } +} + +/// P(Ul) * N(Ur) = N(Ul * Ur) +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<NInt<Ur>> for PInt<Ul> +where + Ul: Mul<Ur>, + <Ul as Mul<Ur>>::Output: Unsigned + NonZero, +{ + type Output = NInt<<Ul as Mul<Ur>>::Output>; + #[inline] + fn mul(self, _: NInt<Ur>) -> Self::Output { + NInt::new() + } +} + +/// N(Ul) * P(Ur) = N(Ul * Ur) +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<PInt<Ur>> for NInt<Ul> +where + Ul: Mul<Ur>, + <Ul as Mul<Ur>>::Output: Unsigned + NonZero, +{ + type Output = NInt<<Ul as Mul<Ur>>::Output>; + #[inline] + fn mul(self, _: PInt<Ur>) -> Self::Output { + NInt::new() + } +} + +// --------------------------------------------------------------------------------------- +// Div + +/// `Z0 / I = Z0` where `I != 0` +impl<I: Integer + NonZero> Div<I> for Z0 { + type Output = Z0; + #[inline] + fn div(self, _: I) -> Self::Output { + Z0 + } +} + +macro_rules! impl_int_div { + ($A:ident, $B:ident, $R:ident) => { + /// `$A<Ul> / $B<Ur> = $R<Ul / Ur>` + impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Div<$B<Ur>> for $A<Ul> + where + Ul: Cmp<Ur>, + $A<Ul>: PrivateDivInt<<Ul as Cmp<Ur>>::Output, $B<Ur>>, + { + type Output = <$A<Ul> as PrivateDivInt<<Ul as Cmp<Ur>>::Output, $B<Ur>>>::Output; + #[inline] + fn div(self, rhs: $B<Ur>) -> Self::Output { + let lhs_cmp_rhs = self.n.compare::<Internal>(&rhs.n); + self.private_div_int(lhs_cmp_rhs, rhs) + } + } + impl<Ul, Ur> PrivateDivInt<Less, $B<Ur>> for $A<Ul> + where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, + { + type Output = Z0; + + #[inline] + fn private_div_int(self, _: Less, _: $B<Ur>) -> Self::Output { + Z0 + } + } + impl<Ul, Ur> PrivateDivInt<Equal, $B<Ur>> for $A<Ul> + where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, + { + type Output = $R<U1>; + + #[inline] + fn private_div_int(self, _: Equal, _: $B<Ur>) -> Self::Output { + $R { n: U1::new() } + } + } + impl<Ul, Ur> PrivateDivInt<Greater, $B<Ur>> for $A<Ul> + where + Ul: Unsigned + NonZero + Div<Ur>, + Ur: Unsigned + NonZero, + <Ul as Div<Ur>>::Output: Unsigned + NonZero, + { + type Output = $R<<Ul as Div<Ur>>::Output>; + + #[inline] + fn private_div_int(self, _: Greater, d: $B<Ur>) -> Self::Output { + $R { n: self.n / d.n } + } + } + }; +} + +impl_int_div!(PInt, PInt, PInt); +impl_int_div!(PInt, NInt, NInt); +impl_int_div!(NInt, PInt, NInt); +impl_int_div!(NInt, NInt, PInt); + +// --------------------------------------------------------------------------------------- +// PartialDiv + +use crate::{PartialDiv, Quot}; + +impl<M, N> PartialDiv<N> for M +where + M: Integer + Div<N> + Rem<N, Output = Z0>, +{ + type Output = Quot<M, N>; + #[inline] + fn partial_div(self, rhs: N) -> Self::Output { + self / rhs + } +} + +// --------------------------------------------------------------------------------------- +// Cmp + +/// 0 == 0 +impl Cmp<Z0> for Z0 { + type Output = Equal; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &Z0) -> Self::Output { + Equal + } +} + +/// 0 > -X +impl<U: Unsigned + NonZero> Cmp<NInt<U>> for Z0 { + type Output = Greater; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &NInt<U>) -> Self::Output { + Greater + } +} + +/// 0 < X +impl<U: Unsigned + NonZero> Cmp<PInt<U>> for Z0 { + type Output = Less; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &PInt<U>) -> Self::Output { + Less + } +} + +/// X > 0 +impl<U: Unsigned + NonZero> Cmp<Z0> for PInt<U> { + type Output = Greater; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &Z0) -> Self::Output { + Greater + } +} + +/// -X < 0 +impl<U: Unsigned + NonZero> Cmp<Z0> for NInt<U> { + type Output = Less; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &Z0) -> Self::Output { + Less + } +} + +/// -X < Y +impl<P: Unsigned + NonZero, N: Unsigned + NonZero> Cmp<PInt<P>> for NInt<N> { + type Output = Less; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &PInt<P>) -> Self::Output { + Less + } +} + +/// X > - Y +impl<P: Unsigned + NonZero, N: Unsigned + NonZero> Cmp<NInt<N>> for PInt<P> { + type Output = Greater; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &NInt<N>) -> Self::Output { + Greater + } +} + +/// X <==> Y +impl<Pl: Cmp<Pr> + Unsigned + NonZero, Pr: Unsigned + NonZero> Cmp<PInt<Pr>> for PInt<Pl> { + type Output = <Pl as Cmp<Pr>>::Output; + + #[inline] + fn compare<IM: InternalMarker>(&self, rhs: &PInt<Pr>) -> Self::Output { + self.n.compare::<Internal>(&rhs.n) + } +} + +/// -X <==> -Y +impl<Nl: Unsigned + NonZero, Nr: Cmp<Nl> + Unsigned + NonZero> Cmp<NInt<Nr>> for NInt<Nl> { + type Output = <Nr as Cmp<Nl>>::Output; + + #[inline] + fn compare<IM: InternalMarker>(&self, rhs: &NInt<Nr>) -> Self::Output { + rhs.n.compare::<Internal>(&self.n) + } +} + +// --------------------------------------------------------------------------------------- +// Rem + +/// `Z0 % I = Z0` where `I != 0` +impl<I: Integer + NonZero> Rem<I> for Z0 { + type Output = Z0; + #[inline] + fn rem(self, _: I) -> Self::Output { + Z0 + } +} + +macro_rules! impl_int_rem { + ($A:ident, $B:ident, $R:ident) => { + /// `$A<Ul> % $B<Ur> = $R<Ul % Ur>` + impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Rem<$B<Ur>> for $A<Ul> + where + Ul: Rem<Ur>, + $A<Ul>: PrivateRem<<Ul as Rem<Ur>>::Output, $B<Ur>>, + { + type Output = <$A<Ul> as PrivateRem<<Ul as Rem<Ur>>::Output, $B<Ur>>>::Output; + #[inline] + fn rem(self, rhs: $B<Ur>) -> Self::Output { + self.private_rem(self.n % rhs.n, rhs) + } + } + impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> PrivateRem<U0, $B<Ur>> for $A<Ul> { + type Output = Z0; + + #[inline] + fn private_rem(self, _: U0, _: $B<Ur>) -> Self::Output { + Z0 + } + } + impl<Ul, Ur, U, B> PrivateRem<UInt<U, B>, $B<Ur>> for $A<Ul> + where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, + U: Unsigned, + B: Bit, + { + type Output = $R<UInt<U, B>>; + + #[inline] + fn private_rem(self, urem: UInt<U, B>, _: $B<Ur>) -> Self::Output { + $R { n: urem } + } + } + }; +} + +impl_int_rem!(PInt, PInt, PInt); +impl_int_rem!(PInt, NInt, PInt); +impl_int_rem!(NInt, PInt, NInt); +impl_int_rem!(NInt, NInt, NInt); + +// --------------------------------------------------------------------------------------- +// Pow + +/// 0^0 = 1 +impl Pow<Z0> for Z0 { + type Output = P1; + #[inline] + fn powi(self, _: Z0) -> Self::Output { + P1::new() + } +} + +/// 0^P = 0 +impl<U: Unsigned + NonZero> Pow<PInt<U>> for Z0 { + type Output = Z0; + #[inline] + fn powi(self, _: PInt<U>) -> Self::Output { + Z0 + } +} + +/// 0^N = 0 +impl<U: Unsigned + NonZero> Pow<NInt<U>> for Z0 { + type Output = Z0; + #[inline] + fn powi(self, _: NInt<U>) -> Self::Output { + Z0 + } +} + +/// 1^N = 1 +impl<U: Unsigned + NonZero> Pow<NInt<U>> for P1 { + type Output = P1; + #[inline] + fn powi(self, _: NInt<U>) -> Self::Output { + P1::new() + } +} + +/// (-1)^N = 1 if N is even +impl<U: Unsigned> Pow<NInt<UInt<U, B0>>> for N1 { + type Output = P1; + #[inline] + fn powi(self, _: NInt<UInt<U, B0>>) -> Self::Output { + P1::new() + } +} + +/// (-1)^N = -1 if N is odd +impl<U: Unsigned> Pow<NInt<UInt<U, B1>>> for N1 { + type Output = N1; + #[inline] + fn powi(self, _: NInt<UInt<U, B1>>) -> Self::Output { + N1::new() + } +} + +/// P^0 = 1 +impl<U: Unsigned + NonZero> Pow<Z0> for PInt<U> { + type Output = P1; + #[inline] + fn powi(self, _: Z0) -> Self::Output { + P1::new() + } +} + +/// N^0 = 1 +impl<U: Unsigned + NonZero> Pow<Z0> for NInt<U> { + type Output = P1; + #[inline] + fn powi(self, _: Z0) -> Self::Output { + P1::new() + } +} + +/// P(Ul)^P(Ur) = P(Ul^Ur) +impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Pow<PInt<Ur>> for PInt<Ul> +where + Ul: Pow<Ur>, + <Ul as Pow<Ur>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<Ul as Pow<Ur>>::Output>; + #[inline] + fn powi(self, _: PInt<Ur>) -> Self::Output { + PInt::new() + } +} + +/// N(Ul)^P(Ur) = P(Ul^Ur) if Ur is even +impl<Ul: Unsigned + NonZero, Ur: Unsigned> Pow<PInt<UInt<Ur, B0>>> for NInt<Ul> +where + Ul: Pow<UInt<Ur, B0>>, + <Ul as Pow<UInt<Ur, B0>>>::Output: Unsigned + NonZero, +{ + type Output = PInt<<Ul as Pow<UInt<Ur, B0>>>::Output>; + #[inline] + fn powi(self, _: PInt<UInt<Ur, B0>>) -> Self::Output { + PInt::new() + } +} + +/// N(Ul)^P(Ur) = N(Ul^Ur) if Ur is odd +impl<Ul: Unsigned + NonZero, Ur: Unsigned> Pow<PInt<UInt<Ur, B1>>> for NInt<Ul> +where + Ul: Pow<UInt<Ur, B1>>, + <Ul as Pow<UInt<Ur, B1>>>::Output: Unsigned + NonZero, +{ + type Output = NInt<<Ul as Pow<UInt<Ur, B1>>>::Output>; + #[inline] + fn powi(self, _: PInt<UInt<Ur, B1>>) -> Self::Output { + NInt::new() + } +} + +// --------------------------------------------------------------------------------------- +// Gcd +use crate::{Gcd, Gcf}; + +impl Gcd<Z0> for Z0 { + type Output = Z0; +} + +impl<U> Gcd<PInt<U>> for Z0 +where + U: Unsigned + NonZero, +{ + type Output = PInt<U>; +} + +impl<U> Gcd<Z0> for PInt<U> +where + U: Unsigned + NonZero, +{ + type Output = PInt<U>; +} + +impl<U> Gcd<NInt<U>> for Z0 +where + U: Unsigned + NonZero, +{ + type Output = PInt<U>; +} + +impl<U> Gcd<Z0> for NInt<U> +where + U: Unsigned + NonZero, +{ + type Output = PInt<U>; +} + +impl<U1, U2> Gcd<PInt<U2>> for PInt<U1> +where + U1: Unsigned + NonZero + Gcd<U2>, + U2: Unsigned + NonZero, + Gcf<U1, U2>: Unsigned + NonZero, +{ + type Output = PInt<Gcf<U1, U2>>; +} + +impl<U1, U2> Gcd<PInt<U2>> for NInt<U1> +where + U1: Unsigned + NonZero + Gcd<U2>, + U2: Unsigned + NonZero, + Gcf<U1, U2>: Unsigned + NonZero, +{ + type Output = PInt<Gcf<U1, U2>>; +} + +impl<U1, U2> Gcd<NInt<U2>> for PInt<U1> +where + U1: Unsigned + NonZero + Gcd<U2>, + U2: Unsigned + NonZero, + Gcf<U1, U2>: Unsigned + NonZero, +{ + type Output = PInt<Gcf<U1, U2>>; +} + +impl<U1, U2> Gcd<NInt<U2>> for NInt<U1> +where + U1: Unsigned + NonZero + Gcd<U2>, + U2: Unsigned + NonZero, + Gcf<U1, U2>: Unsigned + NonZero, +{ + type Output = PInt<Gcf<U1, U2>>; +} + +// --------------------------------------------------------------------------------------- +// Min +use crate::{Max, Maximum, Min, Minimum}; + +impl Min<Z0> for Z0 { + type Output = Z0; + #[inline] + fn min(self, _: Z0) -> Self::Output { + self + } +} + +impl<U> Min<PInt<U>> for Z0 +where + U: Unsigned + NonZero, +{ + type Output = Z0; + #[inline] + fn min(self, _: PInt<U>) -> Self::Output { + self + } +} + +impl<U> Min<NInt<U>> for Z0 +where + U: Unsigned + NonZero, +{ + type Output = NInt<U>; + #[inline] + fn min(self, rhs: NInt<U>) -> Self::Output { + rhs + } +} + +impl<U> Min<Z0> for PInt<U> +where + U: Unsigned + NonZero, +{ + type Output = Z0; + #[inline] + fn min(self, rhs: Z0) -> Self::Output { + rhs + } +} + +impl<U> Min<Z0> for NInt<U> +where + U: Unsigned + NonZero, +{ + type Output = NInt<U>; + #[inline] + fn min(self, _: Z0) -> Self::Output { + self + } +} + +impl<Ul, Ur> Min<PInt<Ur>> for PInt<Ul> +where + Ul: Unsigned + NonZero + Min<Ur>, + Ur: Unsigned + NonZero, + Minimum<Ul, Ur>: Unsigned + NonZero, +{ + type Output = PInt<Minimum<Ul, Ur>>; + #[inline] + fn min(self, rhs: PInt<Ur>) -> Self::Output { + PInt { + n: self.n.min(rhs.n), + } + } +} + +impl<Ul, Ur> Min<PInt<Ur>> for NInt<Ul> +where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, +{ + type Output = NInt<Ul>; + #[inline] + fn min(self, _: PInt<Ur>) -> Self::Output { + self + } +} + +impl<Ul, Ur> Min<NInt<Ur>> for PInt<Ul> +where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, +{ + type Output = NInt<Ur>; + #[inline] + fn min(self, rhs: NInt<Ur>) -> Self::Output { + rhs + } +} + +impl<Ul, Ur> Min<NInt<Ur>> for NInt<Ul> +where + Ul: Unsigned + NonZero + Max<Ur>, + Ur: Unsigned + NonZero, + Maximum<Ul, Ur>: Unsigned + NonZero, +{ + type Output = NInt<Maximum<Ul, Ur>>; + #[inline] + fn min(self, rhs: NInt<Ur>) -> Self::Output { + NInt { + n: self.n.max(rhs.n), + } + } +} + +// --------------------------------------------------------------------------------------- +// Max + +impl Max<Z0> for Z0 { + type Output = Z0; + #[inline] + fn max(self, _: Z0) -> Self::Output { + self + } +} + +impl<U> Max<PInt<U>> for Z0 +where + U: Unsigned + NonZero, +{ + type Output = PInt<U>; + #[inline] + fn max(self, rhs: PInt<U>) -> Self::Output { + rhs + } +} + +impl<U> Max<NInt<U>> for Z0 +where + U: Unsigned + NonZero, +{ + type Output = Z0; + #[inline] + fn max(self, _: NInt<U>) -> Self::Output { + self + } +} + +impl<U> Max<Z0> for PInt<U> +where + U: Unsigned + NonZero, +{ + type Output = PInt<U>; + #[inline] + fn max(self, _: Z0) -> Self::Output { + self + } +} + +impl<U> Max<Z0> for NInt<U> +where + U: Unsigned + NonZero, +{ + type Output = Z0; + #[inline] + fn max(self, rhs: Z0) -> Self::Output { + rhs + } +} + +impl<Ul, Ur> Max<PInt<Ur>> for PInt<Ul> +where + Ul: Unsigned + NonZero + Max<Ur>, + Ur: Unsigned + NonZero, + Maximum<Ul, Ur>: Unsigned + NonZero, +{ + type Output = PInt<Maximum<Ul, Ur>>; + #[inline] + fn max(self, rhs: PInt<Ur>) -> Self::Output { + PInt { + n: self.n.max(rhs.n), + } + } +} + +impl<Ul, Ur> Max<PInt<Ur>> for NInt<Ul> +where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, +{ + type Output = PInt<Ur>; + #[inline] + fn max(self, rhs: PInt<Ur>) -> Self::Output { + rhs + } +} + +impl<Ul, Ur> Max<NInt<Ur>> for PInt<Ul> +where + Ul: Unsigned + NonZero, + Ur: Unsigned + NonZero, +{ + type Output = PInt<Ul>; + #[inline] + fn max(self, _: NInt<Ur>) -> Self::Output { + self + } +} + +impl<Ul, Ur> Max<NInt<Ur>> for NInt<Ul> +where + Ul: Unsigned + NonZero + Min<Ur>, + Ur: Unsigned + NonZero, + Minimum<Ul, Ur>: Unsigned + NonZero, +{ + type Output = NInt<Minimum<Ul, Ur>>; + #[inline] + fn max(self, rhs: NInt<Ur>) -> Self::Output { + NInt { + n: self.n.min(rhs.n), + } + } +} + +// ----------------------------------------- +// ToInt + +impl ToInt<i8> for Z0 { + #[inline] + fn to_int() -> i8 { + Self::I8 + } + const INT: i8 = Self::I8; +} + +impl ToInt<i16> for Z0 { + #[inline] + fn to_int() -> i16 { + Self::I16 + } + const INT: i16 = Self::I16; +} + +impl ToInt<i32> for Z0 { + #[inline] + fn to_int() -> i32 { + Self::I32 + } + const INT: i32 = Self::I32; +} + +impl ToInt<i64> for Z0 { + #[inline] + fn to_int() -> i64 { + Self::I64 + } + const INT: i64 = Self::I64; +} + +// negative numbers + +impl<U> ToInt<i8> for NInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i8 { + Self::I8 + } + const INT: i8 = Self::I8; +} + +impl<U> ToInt<i16> for NInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i16 { + Self::I16 + } + const INT: i16 = Self::I16; +} + +impl<U> ToInt<i32> for NInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i32 { + Self::I32 + } + const INT: i32 = Self::I32; +} + +impl<U> ToInt<i64> for NInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i64 { + Self::I64 + } + const INT: i64 = Self::I64; +} + +// positive numbers + +impl<U> ToInt<i8> for PInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i8 { + Self::I8 + } + const INT: i8 = Self::I8; +} + +impl<U> ToInt<i16> for PInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i16 { + Self::I16 + } + const INT: i16 = Self::I16; +} + +impl<U> ToInt<i32> for PInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i32 { + Self::I32 + } + const INT: i32 = Self::I32; +} + +impl<U> ToInt<i64> for PInt<U> +where + U: Unsigned + NonZero, +{ + #[inline] + fn to_int() -> i64 { + Self::I64 + } + const INT: i64 = Self::I64; +} + +#[cfg(test)] +mod tests { + use crate::{consts::*, Integer, ToInt}; + + #[test] + fn to_ix_min() { + assert_eq!(N128::to_i8(), ::core::i8::MIN); + assert_eq!(N32768::to_i16(), ::core::i16::MIN); + } + + #[test] + fn int_toint_test() { + // i8 + assert_eq!(0_i8, Z0::to_int()); + assert_eq!(1_i8, P1::to_int()); + assert_eq!(2_i8, P2::to_int()); + assert_eq!(3_i8, P3::to_int()); + assert_eq!(4_i8, P4::to_int()); + assert_eq!(-1_i8, N1::to_int()); + assert_eq!(-2_i8, N2::to_int()); + assert_eq!(-3_i8, N3::to_int()); + assert_eq!(-4_i8, N4::to_int()); + assert_eq!(0_i8, Z0::INT); + assert_eq!(1_i8, P1::INT); + assert_eq!(2_i8, P2::INT); + assert_eq!(3_i8, P3::INT); + assert_eq!(4_i8, P4::INT); + assert_eq!(-1_i8, N1::INT); + assert_eq!(-2_i8, N2::INT); + assert_eq!(-3_i8, N3::INT); + assert_eq!(-4_i8, N4::INT); + + // i16 + assert_eq!(0_i16, Z0::to_int()); + assert_eq!(1_i16, P1::to_int()); + assert_eq!(2_i16, P2::to_int()); + assert_eq!(3_i16, P3::to_int()); + assert_eq!(4_i16, P4::to_int()); + assert_eq!(-1_i16, N1::to_int()); + assert_eq!(-2_i16, N2::to_int()); + assert_eq!(-3_i16, N3::to_int()); + assert_eq!(-4_i16, N4::to_int()); + assert_eq!(0_i16, Z0::INT); + assert_eq!(1_i16, P1::INT); + assert_eq!(2_i16, P2::INT); + assert_eq!(3_i16, P3::INT); + assert_eq!(4_i16, P4::INT); + assert_eq!(-1_i16, N1::INT); + assert_eq!(-2_i16, N2::INT); + assert_eq!(-3_i16, N3::INT); + assert_eq!(-4_i16, N4::INT); + + // i32 + assert_eq!(0_i32, Z0::to_int()); + assert_eq!(1_i32, P1::to_int()); + assert_eq!(2_i32, P2::to_int()); + assert_eq!(3_i32, P3::to_int()); + assert_eq!(4_i32, P4::to_int()); + assert_eq!(-1_i32, N1::to_int()); + assert_eq!(-2_i32, N2::to_int()); + assert_eq!(-3_i32, N3::to_int()); + assert_eq!(-4_i32, N4::to_int()); + assert_eq!(0_i32, Z0::INT); + assert_eq!(1_i32, P1::INT); + assert_eq!(2_i32, P2::INT); + assert_eq!(3_i32, P3::INT); + assert_eq!(4_i32, P4::INT); + assert_eq!(-1_i32, N1::INT); + assert_eq!(-2_i32, N2::INT); + assert_eq!(-3_i32, N3::INT); + assert_eq!(-4_i32, N4::INT); + + // i64 + assert_eq!(0_i64, Z0::to_int()); + assert_eq!(1_i64, P1::to_int()); + assert_eq!(2_i64, P2::to_int()); + assert_eq!(3_i64, P3::to_int()); + assert_eq!(4_i64, P4::to_int()); + assert_eq!(-1_i64, N1::to_int()); + assert_eq!(-2_i64, N2::to_int()); + assert_eq!(-3_i64, N3::to_int()); + assert_eq!(-4_i64, N4::to_int()); + assert_eq!(0_i64, Z0::INT); + assert_eq!(1_i64, P1::INT); + assert_eq!(2_i64, P2::INT); + assert_eq!(3_i64, P3::INT); + assert_eq!(4_i64, P4::INT); + assert_eq!(-1_i64, N1::INT); + assert_eq!(-2_i64, N2::INT); + assert_eq!(-3_i64, N3::INT); + assert_eq!(-4_i64, N4::INT); + } +} diff --git a/third_party/rust/typenum/src/lib.rs b/third_party/rust/typenum/src/lib.rs new file mode 100644 index 0000000000..b4a722cb6a --- /dev/null +++ b/third_party/rust/typenum/src/lib.rs @@ -0,0 +1,205 @@ +//! This crate provides type-level numbers evaluated at compile time. It depends only on libcore. +//! +//! The traits defined or used in this crate are used in a typical manner. They can be divided into +//! two categories: **marker traits** and **type operators**. +//! +//! Many of the marker traits have functions defined, but they all do essentially the same thing: +//! convert a type into its runtime counterpart, and are really just there for debugging. For +//! example, +//! +//! ```rust +//! use typenum::{Integer, N4}; +//! +//! assert_eq!(N4::to_i32(), -4); +//! ``` +//! +//! **Type operators** are traits that behave as functions at the type level. These are the meat of +//! this library. Where possible, traits defined in libcore have been used, but their attached +//! functions have not been implemented. +//! +//! For example, the `Add` trait is implemented for both unsigned and signed integers, but the +//! `add` function is not. As there are never any objects of the types defined here, it wouldn't +//! make sense to implement it. What is important is its associated type `Output`, which is where +//! the addition happens. +//! +//! ```rust +//! use std::ops::Add; +//! use typenum::{Integer, P3, P4}; +//! +//! type X = <P3 as Add<P4>>::Output; +//! assert_eq!(<X as Integer>::to_i32(), 7); +//! ``` +//! +//! In addition, helper aliases are defined for type operators. For example, the above snippet +//! could be replaced with +//! +//! ```rust +//! use typenum::{Integer, Sum, P3, P4}; +//! +//! type X = Sum<P3, P4>; +//! assert_eq!(<X as Integer>::to_i32(), 7); +//! ``` +//! +//! Documented in each module is the full list of type operators implemented. + +#![no_std] +#![forbid(unsafe_code)] +#![warn(missing_docs)] +#![cfg_attr(feature = "strict", deny(missing_docs))] +#![cfg_attr(feature = "strict", deny(warnings))] +#![cfg_attr( + feature = "cargo-clippy", + allow( + clippy::len_without_is_empty, + clippy::many_single_char_names, + clippy::new_without_default, + clippy::suspicious_arithmetic_impl, + clippy::type_complexity, + clippy::wrong_self_convention, + ) +)] +#![cfg_attr(feature = "cargo-clippy", deny(clippy::missing_inline_in_public_items))] +#![doc(html_root_url = "https://docs.rs/typenum/1.16.0")] + +// For debugging macros: +// #![feature(trace_macros)] +// trace_macros!(true); + +use core::cmp::Ordering; + +#[cfg(feature = "force_unix_path_separator")] +mod generated { + include!(concat!(env!("OUT_DIR"), "/op.rs")); + include!(concat!(env!("OUT_DIR"), "/consts.rs")); + #[cfg(feature = "const-generics")] + include!(concat!(env!("OUT_DIR"), "/generic_const_mappings.rs")); +} + +#[cfg(not(feature = "force_unix_path_separator"))] +mod generated { + include!(env!("TYPENUM_BUILD_OP")); + include!(env!("TYPENUM_BUILD_CONSTS")); + #[cfg(feature = "const-generics")] + include!(env!("TYPENUM_BUILD_GENERIC_CONSTS")); +} + +pub mod bit; +pub mod int; +pub mod marker_traits; +pub mod operator_aliases; +pub mod private; +pub mod type_operators; +pub mod uint; + +pub mod array; + +pub use crate::{ + array::{ATerm, TArr}, + generated::consts, + int::{NInt, PInt}, + marker_traits::*, + operator_aliases::*, + type_operators::*, + uint::{UInt, UTerm}, +}; + +#[doc(no_inline)] +#[rustfmt::skip] +pub use consts::{ + False, True, B0, B1, + U0, U1, U2, *, + N1, N2, Z0, P1, P2, *, +}; + +#[cfg(feature = "const-generics")] +pub use crate::generated::generic_const_mappings; + +#[cfg(feature = "const-generics")] +#[doc(no_inline)] +pub use generic_const_mappings::{Const, ToUInt, U}; + +/// A potential output from `Cmp`, this is the type equivalent to the enum variant +/// `core::cmp::Ordering::Greater`. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct Greater; + +/// A potential output from `Cmp`, this is the type equivalent to the enum variant +/// `core::cmp::Ordering::Less`. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct Less; + +/// A potential output from `Cmp`, this is the type equivalent to the enum variant +/// `core::cmp::Ordering::Equal`. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct Equal; + +/// Returns `core::cmp::Ordering::Greater` +impl Ord for Greater { + #[inline] + fn to_ordering() -> Ordering { + Ordering::Greater + } +} + +/// Returns `core::cmp::Ordering::Less` +impl Ord for Less { + #[inline] + fn to_ordering() -> Ordering { + Ordering::Less + } +} + +/// Returns `core::cmp::Ordering::Equal` +impl Ord for Equal { + #[inline] + fn to_ordering() -> Ordering { + Ordering::Equal + } +} + +/// Asserts that two types are the same. +#[macro_export] +macro_rules! assert_type_eq { + ($a:ty, $b:ty) => { + const _: core::marker::PhantomData<<$a as $crate::Same<$b>>::Output> = + core::marker::PhantomData; + }; +} + +/// Asserts that a type is `True`, aka `B1`. +#[macro_export] +macro_rules! assert_type { + ($a:ty) => { + const _: core::marker::PhantomData<<$a as $crate::Same<True>>::Output> = + core::marker::PhantomData; + }; +} + +mod sealed { + use crate::{ + ATerm, Bit, Equal, Greater, Less, NInt, NonZero, PInt, TArr, UInt, UTerm, Unsigned, B0, B1, + Z0, + }; + + pub trait Sealed {} + + impl Sealed for B0 {} + impl Sealed for B1 {} + + impl Sealed for UTerm {} + impl<U: Unsigned, B: Bit> Sealed for UInt<U, B> {} + + impl Sealed for Z0 {} + impl<U: Unsigned + NonZero> Sealed for PInt<U> {} + impl<U: Unsigned + NonZero> Sealed for NInt<U> {} + + impl Sealed for Less {} + impl Sealed for Equal {} + impl Sealed for Greater {} + + impl Sealed for ATerm {} + impl<V, A> Sealed for TArr<V, A> {} +} diff --git a/third_party/rust/typenum/src/marker_traits.rs b/third_party/rust/typenum/src/marker_traits.rs new file mode 100644 index 0000000000..2f06e2fba3 --- /dev/null +++ b/third_party/rust/typenum/src/marker_traits.rs @@ -0,0 +1,189 @@ +//! All of the **marker traits** used in typenum. +//! +//! Note that the definition here for marker traits is slightly different than +//! the conventional one -- we include traits with functions that convert a type +//! to the corresponding value, as well as associated constants that do the +//! same. +//! +//! For example, the `Integer` trait includes the function (among others) `fn +//! to_i32() -> i32` and the associated constant `I32` so that one can do this: +//! +//! ``` +//! use typenum::{Integer, N42}; +//! +//! assert_eq!(-42, N42::to_i32()); +//! assert_eq!(-42, N42::I32); +//! ``` + +use crate::sealed::Sealed; + +/// A **marker trait** to designate that a type is not zero. All number types in this +/// crate implement `NonZero` except `B0`, `U0`, and `Z0`. +pub trait NonZero: Sealed {} + +/// A **marker trait** to designate that a type is zero. Only `B0`, `U0`, and `Z0` +/// implement this trait. +pub trait Zero: Sealed {} + +/// A **Marker trait** for the types `Greater`, `Equal`, and `Less`. +pub trait Ord: Sealed { + #[allow(missing_docs)] + fn to_ordering() -> ::core::cmp::Ordering; +} + +/// The **marker trait** for compile time bits. +pub trait Bit: Sealed + Copy + Default + 'static { + #[allow(missing_docs)] + const U8: u8; + #[allow(missing_docs)] + const BOOL: bool; + + /// Instantiates a singleton representing this bit. + fn new() -> Self; + + #[allow(missing_docs)] + fn to_u8() -> u8; + #[allow(missing_docs)] + fn to_bool() -> bool; +} + +/// The **marker trait** for compile time unsigned integers. +/// +/// # Example +/// ```rust +/// use typenum::{Unsigned, U3}; +/// +/// assert_eq!(U3::to_u32(), 3); +/// assert_eq!(U3::I32, 3); +/// ``` +pub trait Unsigned: Sealed + Copy + Default + 'static { + #[allow(missing_docs)] + const U8: u8; + #[allow(missing_docs)] + const U16: u16; + #[allow(missing_docs)] + const U32: u32; + #[allow(missing_docs)] + const U64: u64; + #[cfg(feature = "i128")] + #[allow(missing_docs)] + const U128: u128; + #[allow(missing_docs)] + const USIZE: usize; + + #[allow(missing_docs)] + const I8: i8; + #[allow(missing_docs)] + const I16: i16; + #[allow(missing_docs)] + const I32: i32; + #[allow(missing_docs)] + const I64: i64; + #[cfg(feature = "i128")] + #[allow(missing_docs)] + const I128: i128; + #[allow(missing_docs)] + const ISIZE: isize; + + #[allow(missing_docs)] + fn to_u8() -> u8; + #[allow(missing_docs)] + fn to_u16() -> u16; + #[allow(missing_docs)] + fn to_u32() -> u32; + #[allow(missing_docs)] + fn to_u64() -> u64; + #[cfg(feature = "i128")] + #[allow(missing_docs)] + fn to_u128() -> u128; + #[allow(missing_docs)] + fn to_usize() -> usize; + + #[allow(missing_docs)] + fn to_i8() -> i8; + #[allow(missing_docs)] + fn to_i16() -> i16; + #[allow(missing_docs)] + fn to_i32() -> i32; + #[allow(missing_docs)] + fn to_i64() -> i64; + #[cfg(feature = "i128")] + #[allow(missing_docs)] + fn to_i128() -> i128; + #[allow(missing_docs)] + fn to_isize() -> isize; +} + +/// The **marker trait** for compile time signed integers. +/// +/// # Example +/// ```rust +/// use typenum::{Integer, P3}; +/// +/// assert_eq!(P3::to_i32(), 3); +/// assert_eq!(P3::I32, 3); +/// ``` +pub trait Integer: Sealed + Copy + Default + 'static { + #[allow(missing_docs)] + const I8: i8; + #[allow(missing_docs)] + const I16: i16; + #[allow(missing_docs)] + const I32: i32; + #[allow(missing_docs)] + const I64: i64; + #[cfg(feature = "i128")] + #[allow(missing_docs)] + const I128: i128; + #[allow(missing_docs)] + const ISIZE: isize; + + #[allow(missing_docs)] + fn to_i8() -> i8; + #[allow(missing_docs)] + fn to_i16() -> i16; + #[allow(missing_docs)] + fn to_i32() -> i32; + #[allow(missing_docs)] + fn to_i64() -> i64; + #[cfg(feature = "i128")] + #[allow(missing_docs)] + fn to_i128() -> i128; + #[allow(missing_docs)] + fn to_isize() -> isize; +} + +/// The **marker trait** for type-level arrays of type-level numbers. +/// +/// Someday, it may contain an associated constant to produce a runtime array, +/// like the other marker traits here. However, that is blocked by [this +/// issue](https://github.com/rust-lang/rust/issues/44168). +pub trait TypeArray: Sealed {} + +/// The **marker trait** for type-level numbers which are a power of two. +/// +/// # Examples +/// +/// Here's a working example: +/// +/// ```rust +/// use typenum::{PowerOfTwo, P4, P8}; +/// +/// fn only_p2<P: PowerOfTwo>() {} +/// +/// only_p2::<P4>(); +/// only_p2::<P8>(); +/// ``` +/// +/// Numbers which are not a power of two will fail to compile in this example: +/// +/// ```rust,compile_fail +/// use typenum::{P9, P511, P1023, PowerOfTwo}; +/// +/// fn only_p2<P: PowerOfTwo>() { } +/// +/// only_p2::<P9>(); +/// only_p2::<P511>(); +/// only_p2::<P1023>(); +/// ``` +pub trait PowerOfTwo: Sealed {} diff --git a/third_party/rust/typenum/src/operator_aliases.rs b/third_party/rust/typenum/src/operator_aliases.rs new file mode 100644 index 0000000000..d7eb87f0af --- /dev/null +++ b/third_party/rust/typenum/src/operator_aliases.rs @@ -0,0 +1,109 @@ +//! Aliases for the type operators used in this crate. + +//! Their purpose is to increase the ergonomics of performing operations on the types defined +//! here. For even more ergonomics, consider using the `op!` macro instead. +//! +//! For example, type `X` and type `Y` are the same here: +//! +//! ```rust +//! # #[macro_use] extern crate typenum; +//! use std::ops::Mul; +//! use typenum::{Prod, P5, P7}; +//! +//! type X = <P7 as Mul<P5>>::Output; +//! type Y = Prod<P7, P5>; +//! +//! assert_type_eq!(X, Y); +//! ``` + +// Aliases!!! +use crate::type_operators::{ + Abs, Cmp, Gcd, Len, Logarithm2, Max, Min, PartialDiv, Pow, SquareRoot, +}; +use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub}; + +/// Alias for the associated type of `BitAnd`: `And<A, B> = <A as BitAnd<B>>::Output` +pub type And<A, B> = <A as BitAnd<B>>::Output; +/// Alias for the associated type of `BitOr`: `Or<A, B> = <A as BitOr<B>>::Output` +pub type Or<A, B> = <A as BitOr<B>>::Output; +/// Alias for the associated type of `BitXor`: `Xor<A, B> = <A as BitXor<B>>::Output` +pub type Xor<A, B> = <A as BitXor<B>>::Output; + +/// Alias for the associated type of `Shl`: `Shleft<A, B> = <A as Shl<B>>::Output` +pub type Shleft<A, B> = <A as Shl<B>>::Output; +/// Alias for the associated type of `Shr`: `Shright<A, B> = <A as Shr<B>>::Output` +pub type Shright<A, B> = <A as Shr<B>>::Output; + +/// Alias for the associated type of `Add`: `Sum<A, B> = <A as Add<B>>::Output` +pub type Sum<A, B> = <A as Add<B>>::Output; +/// Alias for the associated type of `Sub`: `Diff<A, B> = <A as Sub<B>>::Output` +pub type Diff<A, B> = <A as Sub<B>>::Output; +/// Alias for the associated type of `Mul`: `Prod<A, B> = <A as Mul<B>>::Output` +pub type Prod<A, B> = <A as Mul<B>>::Output; +/// Alias for the associated type of `Div`: `Quot<A, B> = <A as Div<B>>::Output` +pub type Quot<A, B> = <A as Div<B>>::Output; +/// Alias for the associated type of `Rem`: `Mod<A, B> = <A as Rem<B>>::Output` +pub type Mod<A, B> = <A as Rem<B>>::Output; + +/// Alias for the associated type of +/// `PartialDiv`: `PartialQuot<A, B> = <A as PartialDiv<B>>::Output` +pub type PartialQuot<A, B> = <A as PartialDiv<B>>::Output; + +/// Alias for the associated type of `Neg`: `Negate<A> = <A as Neg>::Output` +pub type Negate<A> = <A as Neg>::Output; + +/// Alias for the associated type of `Abs`: `AbsVal<A> = <A as Abs>::Output` +pub type AbsVal<A> = <A as Abs>::Output; + +/// Alias for the associated type of `Pow`: `Exp<A, B> = <A as Pow<B>>::Output` +pub type Exp<A, B> = <A as Pow<B>>::Output; + +/// Alias for the associated type of `Gcd`: `Gcf<A, B> = <A as Gcd<B>>::Output>` +pub type Gcf<A, B> = <A as Gcd<B>>::Output; + +/// Alias to make it easy to add 1: `Add1<A> = <A as Add<B1>>::Output` +pub type Add1<A> = <A as Add<crate::bit::B1>>::Output; +/// Alias to make it easy to subtract 1: `Sub1<A> = <A as Sub<B1>>::Output` +pub type Sub1<A> = <A as Sub<crate::bit::B1>>::Output; + +/// Alias to make it easy to multiply by 2. `Double<A> = Shleft<A, B1>` +pub type Double<A> = Shleft<A, crate::bit::B1>; + +/// Alias to make it easy to square. `Square<A> = <A as Mul<A>>::Output` +pub type Square<A> = <A as Mul>::Output; +/// Alias to make it easy to cube. `Cube<A> = <Square<A> as Mul<A>>::Output` +pub type Cube<A> = <Square<A> as Mul<A>>::Output; + +/// Alias for the associated type of `SquareRoot`: `Sqrt<A> = <A as SquareRoot>::Output` +pub type Sqrt<A> = <A as SquareRoot>::Output; + +/// Alias for the associated type of `Cmp`: `Compare<A, B> = <A as Cmp<B>>::Output` +pub type Compare<A, B> = <A as Cmp<B>>::Output; + +/// Alias for the associated type of `Len`: `Length<A> = <A as Len>::Output` +pub type Length<T> = <T as Len>::Output; + +/// Alias for the associated type of `Min`: `Minimum<A, B> = <A as Min<B>>::Output` +pub type Minimum<A, B> = <A as Min<B>>::Output; + +/// Alias for the associated type of `Max`: `Maximum<A, B> = <A as Max<B>>::Output` +pub type Maximum<A, B> = <A as Max<B>>::Output; + +use crate::type_operators::{ + IsEqual, IsGreater, IsGreaterOrEqual, IsLess, IsLessOrEqual, IsNotEqual, +}; +/// Alias for the associated type of `IsLess`: `Le<A, B> = <A as IsLess<B>>::Output` +pub type Le<A, B> = <A as IsLess<B>>::Output; +/// Alias for the associated type of `IsEqual`: `Eq<A, B> = <A as IsEqual<B>>::Output` +pub type Eq<A, B> = <A as IsEqual<B>>::Output; +/// Alias for the associated type of `IsGreater`: `Gr<A, B> = <A as IsGreater<B>>::Output` +pub type Gr<A, B> = <A as IsGreater<B>>::Output; +/// Alias for the associated type of `IsGreaterOrEqual`: +/// `GrEq<A, B> = <A as IsGreaterOrEqual<B>>::Output` +pub type GrEq<A, B> = <A as IsGreaterOrEqual<B>>::Output; +/// Alias for the associated type of `IsLessOrEqual`: `LeEq<A, B> = <A as IsLessOrEqual<B>>::Output` +pub type LeEq<A, B> = <A as IsLessOrEqual<B>>::Output; +/// Alias for the associated type of `IsNotEqual`: `NotEq<A, B> = <A as IsNotEqual<B>>::Output` +pub type NotEq<A, B> = <A as IsNotEqual<B>>::Output; +/// Alias for the associated type of `Logarithm2`: `Log2<A> = <A as Logarithm2>::Output` +pub type Log2<A> = <A as Logarithm2>::Output; diff --git a/third_party/rust/typenum/src/private.rs b/third_party/rust/typenum/src/private.rs new file mode 100644 index 0000000000..97b2ad80f6 --- /dev/null +++ b/third_party/rust/typenum/src/private.rs @@ -0,0 +1,587 @@ +//! **Ignore me!** This module is for things that are conceptually private but that must +//! be made public for typenum to work correctly. +//! +//! Unless you are working on typenum itself, **there is no need to view anything here**. +//! +//! Certainly don't implement any of the traits here for anything. +//! +//! +//! Just look away. +//! +//! +//! Loooooooooooooooooooooooooooooooooook awaaaaaaaaaaaayyyyyyyyyyyyyyyyyyyyyyyyyyyyy... +//! +//! +//! If you do manage to find something of use in here, please let me know. If you can make a +//! compelling case, it may be moved out of __private. +//! +//! Note: Aliases for private type operators will all be named simply that operator followed +//! by an abbreviated name of its associated type. + +#![doc(hidden)] + +use crate::{ + bit::{Bit, B0, B1}, + uint::{UInt, UTerm, Unsigned}, +}; + +/// A marker for restricting a method on a public trait to internal use only. +pub(crate) enum Internal {} + +pub trait InternalMarker {} + +impl InternalMarker for Internal {} + +/// Convenience trait. Calls `Invert` -> `TrimTrailingZeros` -> `Invert` +pub trait Trim { + type Output; + + fn trim(self) -> Self::Output; +} +pub type TrimOut<A> = <A as Trim>::Output; + +/// Gets rid of all zeros until it hits a one. + +// ONLY IMPLEMENT FOR INVERTED NUMBERS! +pub trait TrimTrailingZeros { + type Output; + + fn trim_trailing_zeros(self) -> Self::Output; +} +pub type TrimTrailingZerosOut<A> = <A as TrimTrailingZeros>::Output; + +/// Converts between standard numbers and inverted ones that have the most significant +/// digit on the outside. +pub trait Invert { + type Output; + + fn invert(self) -> Self::Output; +} +pub type InvertOut<A> = <A as Invert>::Output; + +/// Doubly private! Called by invert to make the magic happen once its done the first step. +/// The Rhs is what we've got so far. +pub trait PrivateInvert<Rhs> { + type Output; + + fn private_invert(self, rhs: Rhs) -> Self::Output; +} +pub type PrivateInvertOut<A, Rhs> = <A as PrivateInvert<Rhs>>::Output; + +/// Terminating character for `InvertedUInt`s +pub struct InvertedUTerm; + +/// Inverted `UInt` (has most significant digit on the outside) +pub struct InvertedUInt<IU: InvertedUnsigned, B: Bit> { + msb: IU, + lsb: B, +} + +/// Does the real anding for `UInt`s; `And` just calls this and then `Trim`. +pub trait PrivateAnd<Rhs = Self> { + type Output; + + fn private_and(self, rhs: Rhs) -> Self::Output; +} +pub type PrivateAndOut<A, Rhs> = <A as PrivateAnd<Rhs>>::Output; + +/// Does the real xoring for `UInt`s; `Xor` just calls this and then `Trim`. +pub trait PrivateXor<Rhs = Self> { + type Output; + + fn private_xor(self, rhs: Rhs) -> Self::Output; +} +pub type PrivateXorOut<A, Rhs> = <A as PrivateXor<Rhs>>::Output; + +/// Does the real subtraction for `UInt`s; `Sub` just calls this and then `Trim`. +pub trait PrivateSub<Rhs = Self> { + type Output; + + fn private_sub(self, rhs: Rhs) -> Self::Output; +} +pub type PrivateSubOut<A, Rhs> = <A as PrivateSub<Rhs>>::Output; + +/// Used for addition of signed integers; `C = P.cmp(N)` +/// Assumes `P = Self` is positive and `N` is negative +/// where `P` and `N` are both passed as unsigned integers +pub trait PrivateIntegerAdd<C, N> { + type Output; + + fn private_integer_add(self, _: C, _: N) -> Self::Output; +} +pub type PrivateIntegerAddOut<P, C, N> = <P as PrivateIntegerAdd<C, N>>::Output; + +pub trait PrivatePow<Y, N> { + type Output; + + fn private_pow(self, _: Y, _: N) -> Self::Output; +} +pub type PrivatePowOut<A, Y, N> = <A as PrivatePow<Y, N>>::Output; + +/// Performs `Shl` on `Lhs` so that `SizeOf(Lhs) = SizeOf(Rhs)` +/// Fails if `SizeOf(Lhs) > SizeOf(Rhs)` +pub trait ShiftDiff<Rhs> { + type Output; +} +pub type ShiftDiffOut<A, Rhs> = <A as ShiftDiff<Rhs>>::Output; + +/// Gives `SizeOf(Lhs) - SizeOf(Rhs)` +pub trait BitDiff<Rhs> { + type Output; +} +pub type BitDiffOut<A, Rhs> = <A as BitDiff<Rhs>>::Output; + +/// Inverted unsigned numbers +pub trait InvertedUnsigned { + fn to_u64() -> u64; +} + +impl InvertedUnsigned for InvertedUTerm { + #[inline] + fn to_u64() -> u64 { + 0 + } +} + +impl<IU: InvertedUnsigned, B: Bit> InvertedUnsigned for InvertedUInt<IU, B> { + #[inline] + fn to_u64() -> u64 { + u64::from(B::to_u8()) | IU::to_u64() << 1 + } +} + +impl Invert for UTerm { + type Output = InvertedUTerm; + + #[inline] + fn invert(self) -> Self::Output { + InvertedUTerm + } +} + +impl<U: Unsigned, B: Bit> Invert for UInt<U, B> +where + U: PrivateInvert<InvertedUInt<InvertedUTerm, B>>, +{ + type Output = PrivateInvertOut<U, InvertedUInt<InvertedUTerm, B>>; + + #[inline] + fn invert(self) -> Self::Output { + self.msb.private_invert(InvertedUInt { + msb: InvertedUTerm, + lsb: self.lsb, + }) + } +} + +impl<IU: InvertedUnsigned> PrivateInvert<IU> for UTerm { + type Output = IU; + + #[inline] + fn private_invert(self, rhs: IU) -> Self::Output { + rhs + } +} + +impl<IU: InvertedUnsigned, U: Unsigned, B: Bit> PrivateInvert<IU> for UInt<U, B> +where + U: PrivateInvert<InvertedUInt<IU, B>>, +{ + type Output = PrivateInvertOut<U, InvertedUInt<IU, B>>; + + #[inline] + fn private_invert(self, rhs: IU) -> Self::Output { + self.msb.private_invert(InvertedUInt { + msb: rhs, + lsb: self.lsb, + }) + } +} + +#[test] +fn test_inversion() { + type Test4 = <crate::consts::U4 as Invert>::Output; + type Test5 = <crate::consts::U5 as Invert>::Output; + type Test12 = <crate::consts::U12 as Invert>::Output; + type Test16 = <crate::consts::U16 as Invert>::Output; + + assert_eq!(1, <Test4 as InvertedUnsigned>::to_u64()); + assert_eq!(5, <Test5 as InvertedUnsigned>::to_u64()); + assert_eq!(3, <Test12 as InvertedUnsigned>::to_u64()); + assert_eq!(1, <Test16 as InvertedUnsigned>::to_u64()); +} + +impl Invert for InvertedUTerm { + type Output = UTerm; + + #[inline] + fn invert(self) -> Self::Output { + UTerm + } +} + +impl<IU: InvertedUnsigned, B: Bit> Invert for InvertedUInt<IU, B> +where + IU: PrivateInvert<UInt<UTerm, B>>, +{ + type Output = <IU as PrivateInvert<UInt<UTerm, B>>>::Output; + + #[inline] + fn invert(self) -> Self::Output { + self.msb.private_invert(UInt { + msb: UTerm, + lsb: self.lsb, + }) + } +} + +impl<U: Unsigned> PrivateInvert<U> for InvertedUTerm { + type Output = U; + + #[inline] + fn private_invert(self, rhs: U) -> Self::Output { + rhs + } +} + +impl<U: Unsigned, IU: InvertedUnsigned, B: Bit> PrivateInvert<U> for InvertedUInt<IU, B> +where + IU: PrivateInvert<UInt<U, B>>, +{ + type Output = <IU as PrivateInvert<UInt<U, B>>>::Output; + + #[inline] + fn private_invert(self, rhs: U) -> Self::Output { + self.msb.private_invert(UInt { + msb: rhs, + lsb: self.lsb, + }) + } +} + +#[test] +fn test_double_inversion() { + type Test4 = <<crate::consts::U4 as Invert>::Output as Invert>::Output; + type Test5 = <<crate::consts::U5 as Invert>::Output as Invert>::Output; + type Test12 = <<crate::consts::U12 as Invert>::Output as Invert>::Output; + type Test16 = <<crate::consts::U16 as Invert>::Output as Invert>::Output; + + assert_eq!(4, <Test4 as Unsigned>::to_u64()); + assert_eq!(5, <Test5 as Unsigned>::to_u64()); + assert_eq!(12, <Test12 as Unsigned>::to_u64()); + assert_eq!(16, <Test16 as Unsigned>::to_u64()); +} + +impl TrimTrailingZeros for InvertedUTerm { + type Output = InvertedUTerm; + + #[inline] + fn trim_trailing_zeros(self) -> Self::Output { + InvertedUTerm + } +} + +impl<IU: InvertedUnsigned> TrimTrailingZeros for InvertedUInt<IU, B1> { + type Output = Self; + + #[inline] + fn trim_trailing_zeros(self) -> Self::Output { + self + } +} + +impl<IU: InvertedUnsigned> TrimTrailingZeros for InvertedUInt<IU, B0> +where + IU: TrimTrailingZeros, +{ + type Output = <IU as TrimTrailingZeros>::Output; + + #[inline] + fn trim_trailing_zeros(self) -> Self::Output { + self.msb.trim_trailing_zeros() + } +} + +impl<U: Unsigned> Trim for U +where + U: Invert, + <U as Invert>::Output: TrimTrailingZeros, + <<U as Invert>::Output as TrimTrailingZeros>::Output: Invert, +{ + type Output = <<<U as Invert>::Output as TrimTrailingZeros>::Output as Invert>::Output; + + #[inline] + fn trim(self) -> Self::Output { + self.invert().trim_trailing_zeros().invert() + } +} + +// Note: Trimming is tested when we do subtraction. + +pub trait PrivateCmp<Rhs, SoFar> { + type Output; + + fn private_cmp(&self, _: &Rhs, _: SoFar) -> Self::Output; +} +pub type PrivateCmpOut<A, Rhs, SoFar> = <A as PrivateCmp<Rhs, SoFar>>::Output; + +// Set Bit +pub trait PrivateSetBit<I, B> { + type Output; + + fn private_set_bit(self, _: I, _: B) -> Self::Output; +} +pub type PrivateSetBitOut<N, I, B> = <N as PrivateSetBit<I, B>>::Output; + +// Div +pub trait PrivateDiv<N, D, Q, R, I> { + type Quotient; + type Remainder; + + fn private_div_quotient(self, _: N, _: D, _: Q, _: R, _: I) -> Self::Quotient; + + fn private_div_remainder(self, _: N, _: D, _: Q, _: R, _: I) -> Self::Remainder; +} + +pub type PrivateDivQuot<N, D, Q, R, I> = <() as PrivateDiv<N, D, Q, R, I>>::Quotient; +pub type PrivateDivRem<N, D, Q, R, I> = <() as PrivateDiv<N, D, Q, R, I>>::Remainder; + +pub trait PrivateDivIf<N, D, Q, R, I, RcmpD> { + type Quotient; + type Remainder; + + fn private_div_if_quotient(self, _: N, _: D, _: Q, _: R, _: I, _: RcmpD) -> Self::Quotient; + + fn private_div_if_remainder(self, _: N, _: D, _: Q, _: R, _: I, _: RcmpD) -> Self::Remainder; +} + +pub type PrivateDivIfQuot<N, D, Q, R, I, RcmpD> = + <() as PrivateDivIf<N, D, Q, R, I, RcmpD>>::Quotient; +pub type PrivateDivIfRem<N, D, Q, R, I, RcmpD> = + <() as PrivateDivIf<N, D, Q, R, I, RcmpD>>::Remainder; + +// Div for signed ints +pub trait PrivateDivInt<C, Divisor> { + type Output; + + fn private_div_int(self, _: C, _: Divisor) -> Self::Output; +} +pub type PrivateDivIntOut<A, C, Divisor> = <A as PrivateDivInt<C, Divisor>>::Output; + +pub trait PrivateRem<URem, Divisor> { + type Output; + + fn private_rem(self, _: URem, _: Divisor) -> Self::Output; +} +pub type PrivateRemOut<A, URem, Divisor> = <A as PrivateRem<URem, Divisor>>::Output; + +// min max +pub trait PrivateMin<Rhs, CmpResult> { + type Output; + fn private_min(self, rhs: Rhs) -> Self::Output; +} +pub type PrivateMinOut<A, B, CmpResult> = <A as PrivateMin<B, CmpResult>>::Output; + +pub trait PrivateMax<Rhs, CmpResult> { + type Output; + fn private_max(self, rhs: Rhs) -> Self::Output; +} +pub type PrivateMaxOut<A, B, CmpResult> = <A as PrivateMax<B, CmpResult>>::Output; + +// Comparisons + +use crate::{Equal, False, Greater, Less, True}; + +pub trait IsLessPrivate<Rhs, Cmp> { + type Output: Bit; + + fn is_less_private(self, _: Rhs, _: Cmp) -> Self::Output; +} + +impl<A, B> IsLessPrivate<B, Less> for A { + type Output = True; + + #[inline] + fn is_less_private(self, _: B, _: Less) -> Self::Output { + B1 + } +} +impl<A, B> IsLessPrivate<B, Equal> for A { + type Output = False; + + #[inline] + fn is_less_private(self, _: B, _: Equal) -> Self::Output { + B0 + } +} +impl<A, B> IsLessPrivate<B, Greater> for A { + type Output = False; + + #[inline] + fn is_less_private(self, _: B, _: Greater) -> Self::Output { + B0 + } +} + +pub trait IsEqualPrivate<Rhs, Cmp> { + type Output: Bit; + + fn is_equal_private(self, _: Rhs, _: Cmp) -> Self::Output; +} + +impl<A, B> IsEqualPrivate<B, Less> for A { + type Output = False; + + #[inline] + fn is_equal_private(self, _: B, _: Less) -> Self::Output { + B0 + } +} +impl<A, B> IsEqualPrivate<B, Equal> for A { + type Output = True; + + #[inline] + fn is_equal_private(self, _: B, _: Equal) -> Self::Output { + B1 + } +} +impl<A, B> IsEqualPrivate<B, Greater> for A { + type Output = False; + + #[inline] + fn is_equal_private(self, _: B, _: Greater) -> Self::Output { + B0 + } +} + +pub trait IsGreaterPrivate<Rhs, Cmp> { + type Output: Bit; + + fn is_greater_private(self, _: Rhs, _: Cmp) -> Self::Output; +} + +impl<A, B> IsGreaterPrivate<B, Less> for A { + type Output = False; + + #[inline] + fn is_greater_private(self, _: B, _: Less) -> Self::Output { + B0 + } +} +impl<A, B> IsGreaterPrivate<B, Equal> for A { + type Output = False; + + #[inline] + fn is_greater_private(self, _: B, _: Equal) -> Self::Output { + B0 + } +} +impl<A, B> IsGreaterPrivate<B, Greater> for A { + type Output = True; + + #[inline] + fn is_greater_private(self, _: B, _: Greater) -> Self::Output { + B1 + } +} + +pub trait IsLessOrEqualPrivate<Rhs, Cmp> { + type Output: Bit; + + fn is_less_or_equal_private(self, _: Rhs, _: Cmp) -> Self::Output; +} + +impl<A, B> IsLessOrEqualPrivate<B, Less> for A { + type Output = True; + + #[inline] + fn is_less_or_equal_private(self, _: B, _: Less) -> Self::Output { + B1 + } +} +impl<A, B> IsLessOrEqualPrivate<B, Equal> for A { + type Output = True; + + #[inline] + fn is_less_or_equal_private(self, _: B, _: Equal) -> Self::Output { + B1 + } +} +impl<A, B> IsLessOrEqualPrivate<B, Greater> for A { + type Output = False; + + #[inline] + fn is_less_or_equal_private(self, _: B, _: Greater) -> Self::Output { + B0 + } +} + +pub trait IsNotEqualPrivate<Rhs, Cmp> { + type Output: Bit; + + fn is_not_equal_private(self, _: Rhs, _: Cmp) -> Self::Output; +} + +impl<A, B> IsNotEqualPrivate<B, Less> for A { + type Output = True; + + #[inline] + fn is_not_equal_private(self, _: B, _: Less) -> Self::Output { + B1 + } +} +impl<A, B> IsNotEqualPrivate<B, Equal> for A { + type Output = False; + + #[inline] + fn is_not_equal_private(self, _: B, _: Equal) -> Self::Output { + B0 + } +} +impl<A, B> IsNotEqualPrivate<B, Greater> for A { + type Output = True; + + #[inline] + fn is_not_equal_private(self, _: B, _: Greater) -> Self::Output { + B1 + } +} + +pub trait IsGreaterOrEqualPrivate<Rhs, Cmp> { + type Output: Bit; + + fn is_greater_or_equal_private(self, _: Rhs, _: Cmp) -> Self::Output; +} + +impl<A, B> IsGreaterOrEqualPrivate<B, Less> for A { + type Output = False; + + #[inline] + fn is_greater_or_equal_private(self, _: B, _: Less) -> Self::Output { + B0 + } +} +impl<A, B> IsGreaterOrEqualPrivate<B, Equal> for A { + type Output = True; + + #[inline] + fn is_greater_or_equal_private(self, _: B, _: Equal) -> Self::Output { + B1 + } +} +impl<A, B> IsGreaterOrEqualPrivate<B, Greater> for A { + type Output = True; + + #[inline] + fn is_greater_or_equal_private(self, _: B, _: Greater) -> Self::Output { + B1 + } +} + +pub trait PrivateSquareRoot { + type Output; +} + +pub trait PrivateLogarithm2 { + type Output; +} diff --git a/third_party/rust/typenum/src/type_operators.rs b/third_party/rust/typenum/src/type_operators.rs new file mode 100644 index 0000000000..d476614ae8 --- /dev/null +++ b/third_party/rust/typenum/src/type_operators.rs @@ -0,0 +1,592 @@ +//! Useful **type operators** that are not defined in `core::ops`. + +use crate::{ + private::{Internal, InternalMarker}, + Bit, NInt, NonZero, PInt, UInt, UTerm, Unsigned, Z0, +}; + +/// A **type operator** that ensures that `Rhs` is the same as `Self`, it is mainly useful +/// for writing macros that can take arbitrary binary or unary operators. +/// +/// `Same` is implemented generically for all types; it should never need to be implemented +/// for anything else. +/// +/// Note that Rust lazily evaluates types, so this will only fail for two different types if +/// the `Output` is used. +/// +/// # Example +/// ```rust +/// use typenum::{Same, Unsigned, U4, U5}; +/// +/// assert_eq!(<U5 as Same<U5>>::Output::to_u32(), 5); +/// +/// // Only an error if we use it: +/// # #[allow(dead_code)] +/// type Undefined = <U5 as Same<U4>>::Output; +/// // Compiler error: +/// // Undefined::to_u32(); +/// ``` +pub trait Same<Rhs = Self> { + /// Should always be `Self` + type Output; +} + +impl<T> Same<T> for T { + type Output = T; +} + +/// A **type operator** that returns the absolute value. +/// +/// # Example +/// ```rust +/// use typenum::{Abs, Integer, N5}; +/// +/// assert_eq!(<N5 as Abs>::Output::to_i32(), 5); +/// ``` +pub trait Abs { + /// The absolute value. + type Output; +} + +impl Abs for Z0 { + type Output = Z0; +} + +impl<U: Unsigned + NonZero> Abs for PInt<U> { + type Output = Self; +} + +impl<U: Unsigned + NonZero> Abs for NInt<U> { + type Output = PInt<U>; +} + +/// A **type operator** that provides exponentiation by repeated squaring. +/// +/// # Example +/// ```rust +/// use typenum::{Integer, Pow, N3, P3}; +/// +/// assert_eq!(<N3 as Pow<P3>>::Output::to_i32(), -27); +/// ``` +pub trait Pow<Exp> { + /// The result of the exponentiation. + type Output; + /// This function isn't used in this crate, but may be useful for others. + /// It is implemented for primitives. + /// + /// # Example + /// ```rust + /// use typenum::{Pow, U3}; + /// + /// let a = 7u32.powi(U3::new()); + /// let b = 7u32.pow(3); + /// assert_eq!(a, b); + /// + /// let x = 3.0.powi(U3::new()); + /// let y = 27.0; + /// assert_eq!(x, y); + /// ``` + fn powi(self, exp: Exp) -> Self::Output; +} + +macro_rules! impl_pow_f { + ($t:ty) => { + impl Pow<UTerm> for $t { + type Output = $t; + #[inline] + fn powi(self, _: UTerm) -> Self::Output { + 1.0 + } + } + + impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t { + type Output = $t; + // powi is unstable in core, so we have to write this function ourselves. + // copied from num::pow::pow + #[inline] + fn powi(self, _: UInt<U, B>) -> Self::Output { + let mut exp = <UInt<U, B> as Unsigned>::to_u32(); + let mut base = self; + + if exp == 0 { + return 1.0; + } + + while exp & 1 == 0 { + base *= base; + exp >>= 1; + } + if exp == 1 { + return base; + } + + let mut acc = base.clone(); + while exp > 1 { + exp >>= 1; + base *= base; + if exp & 1 == 1 { + acc *= base.clone(); + } + } + acc + } + } + + impl Pow<Z0> for $t { + type Output = $t; + #[inline] + fn powi(self, _: Z0) -> Self::Output { + 1.0 + } + } + + impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t { + type Output = $t; + // powi is unstable in core, so we have to write this function ourselves. + // copied from num::pow::pow + #[inline] + fn powi(self, _: PInt<U>) -> Self::Output { + let mut exp = U::to_u32(); + let mut base = self; + + if exp == 0 { + return 1.0; + } + + while exp & 1 == 0 { + base *= base; + exp >>= 1; + } + if exp == 1 { + return base; + } + + let mut acc = base.clone(); + while exp > 1 { + exp >>= 1; + base *= base; + if exp & 1 == 1 { + acc *= base.clone(); + } + } + acc + } + } + + impl<U: Unsigned + NonZero> Pow<NInt<U>> for $t { + type Output = $t; + + #[inline] + fn powi(self, _: NInt<U>) -> Self::Output { + <$t as Pow<PInt<U>>>::powi(self, PInt::new()).recip() + } + } + }; +} + +impl_pow_f!(f32); +impl_pow_f!(f64); + +macro_rules! impl_pow_i { + () => (); + ($t: ty $(, $tail:tt)*) => ( + impl Pow<UTerm> for $t { + type Output = $t; + #[inline] + fn powi(self, _: UTerm) -> Self::Output { + 1 + } + } + + impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t { + type Output = $t; + #[inline] + fn powi(self, _: UInt<U, B>) -> Self::Output { + self.pow(<UInt<U, B> as Unsigned>::to_u32()) + } + } + + impl Pow<Z0> for $t { + type Output = $t; + #[inline] + fn powi(self, _: Z0) -> Self::Output { + 1 + } + } + + impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t { + type Output = $t; + #[inline] + fn powi(self, _: PInt<U>) -> Self::Output { + self.pow(U::to_u32()) + } + } + + impl_pow_i!($($tail),*); + ); +} + +impl_pow_i!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); +#[cfg(feature = "i128")] +impl_pow_i!(u128, i128); + +#[test] +fn pow_test() { + use crate::consts::*; + let z0 = Z0::new(); + let p3 = P3::new(); + + let u0 = U0::new(); + let u3 = U3::new(); + let n3 = N3::new(); + + macro_rules! check { + ($x:ident) => { + assert_eq!($x.powi(z0), 1); + assert_eq!($x.powi(u0), 1); + + assert_eq!($x.powi(p3), $x * $x * $x); + assert_eq!($x.powi(u3), $x * $x * $x); + }; + ($x:ident, $f:ident) => { + assert!((<$f as Pow<Z0>>::powi(*$x, z0) - 1.0).abs() < ::core::$f::EPSILON); + assert!((<$f as Pow<U0>>::powi(*$x, u0) - 1.0).abs() < ::core::$f::EPSILON); + + assert!((<$f as Pow<P3>>::powi(*$x, p3) - $x * $x * $x).abs() < ::core::$f::EPSILON); + assert!((<$f as Pow<U3>>::powi(*$x, u3) - $x * $x * $x).abs() < ::core::$f::EPSILON); + + if *$x == 0.0 { + assert!(<$f as Pow<N3>>::powi(*$x, n3).is_infinite()); + } else { + assert!( + (<$f as Pow<N3>>::powi(*$x, n3) - 1. / $x / $x / $x).abs() + < ::core::$f::EPSILON + ); + } + }; + } + + for x in &[0i8, -3, 2] { + check!(x); + } + for x in &[0u8, 1, 5] { + check!(x); + } + for x in &[0usize, 1, 5, 40] { + check!(x); + } + for x in &[0isize, 1, 2, -30, -22, 48] { + check!(x); + } + for x in &[0.0f32, 2.2, -3.5, 378.223] { + check!(x, f32); + } + for x in &[0.0f64, 2.2, -3.5, -2387.2, 234.22] { + check!(x, f64); + } +} + +/// A **type operator** for comparing `Self` and `Rhs`. It provides a similar functionality to +/// the function +/// [`core::cmp::Ord::cmp`](https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html#tymethod.cmp) +/// but for types. +/// +/// # Example +/// ```rust +/// use typenum::{Cmp, Ord, N3, P2, P5}; +/// use std::cmp::Ordering; +/// +/// assert_eq!(<P2 as Cmp<N3>>::Output::to_ordering(), Ordering::Greater); +/// assert_eq!(<P2 as Cmp<P2>>::Output::to_ordering(), Ordering::Equal); +/// assert_eq!(<P2 as Cmp<P5>>::Output::to_ordering(), Ordering::Less); +pub trait Cmp<Rhs = Self> { + /// The result of the comparison. It should only ever be one of `Greater`, `Less`, or `Equal`. + type Output; + + #[doc(hidden)] + fn compare<IM: InternalMarker>(&self, _: &Rhs) -> Self::Output; +} + +/// A **type operator** that gives the length of an `Array` or the number of bits in a `UInt`. +pub trait Len { + /// The length as a type-level unsigned integer. + type Output: crate::Unsigned; + /// This function isn't used in this crate, but may be useful for others. + fn len(&self) -> Self::Output; +} + +/// Division as a partial function. This **type operator** performs division just as `Div`, but is +/// only defined when the result is an integer (i.e. there is no remainder). +pub trait PartialDiv<Rhs = Self> { + /// The type of the result of the division + type Output; + /// Method for performing the division + fn partial_div(self, _: Rhs) -> Self::Output; +} + +/// A **type operator** that returns the minimum of `Self` and `Rhs`. +pub trait Min<Rhs = Self> { + /// The type of the minimum of `Self` and `Rhs` + type Output; + /// Method returning the minimum + fn min(self, rhs: Rhs) -> Self::Output; +} + +/// A **type operator** that returns the maximum of `Self` and `Rhs`. +pub trait Max<Rhs = Self> { + /// The type of the maximum of `Self` and `Rhs` + type Output; + /// Method returning the maximum + fn max(self, rhs: Rhs) -> Self::Output; +} + +use crate::Compare; + +/// A **type operator** that returns `True` if `Self < Rhs`, otherwise returns `False`. +pub trait IsLess<Rhs = Self> { + /// The type representing either `True` or `False` + type Output: Bit; + /// Method returning `True` or `False`. + fn is_less(self, rhs: Rhs) -> Self::Output; +} + +use crate::private::IsLessPrivate; +impl<A, B> IsLess<B> for A +where + A: Cmp<B> + IsLessPrivate<B, Compare<A, B>>, +{ + type Output = <A as IsLessPrivate<B, Compare<A, B>>>::Output; + + #[inline] + fn is_less(self, rhs: B) -> Self::Output { + let lhs_cmp_rhs = self.compare::<Internal>(&rhs); + self.is_less_private(rhs, lhs_cmp_rhs) + } +} + +/// A **type operator** that returns `True` if `Self == Rhs`, otherwise returns `False`. +pub trait IsEqual<Rhs = Self> { + /// The type representing either `True` or `False` + type Output: Bit; + /// Method returning `True` or `False`. + fn is_equal(self, rhs: Rhs) -> Self::Output; +} + +use crate::private::IsEqualPrivate; +impl<A, B> IsEqual<B> for A +where + A: Cmp<B> + IsEqualPrivate<B, Compare<A, B>>, +{ + type Output = <A as IsEqualPrivate<B, Compare<A, B>>>::Output; + + #[inline] + fn is_equal(self, rhs: B) -> Self::Output { + let lhs_cmp_rhs = self.compare::<Internal>(&rhs); + self.is_equal_private(rhs, lhs_cmp_rhs) + } +} + +/// A **type operator** that returns `True` if `Self > Rhs`, otherwise returns `False`. +pub trait IsGreater<Rhs = Self> { + /// The type representing either `True` or `False` + type Output: Bit; + /// Method returning `True` or `False`. + fn is_greater(self, rhs: Rhs) -> Self::Output; +} + +use crate::private::IsGreaterPrivate; +impl<A, B> IsGreater<B> for A +where + A: Cmp<B> + IsGreaterPrivate<B, Compare<A, B>>, +{ + type Output = <A as IsGreaterPrivate<B, Compare<A, B>>>::Output; + + #[inline] + fn is_greater(self, rhs: B) -> Self::Output { + let lhs_cmp_rhs = self.compare::<Internal>(&rhs); + self.is_greater_private(rhs, lhs_cmp_rhs) + } +} + +/// A **type operator** that returns `True` if `Self <= Rhs`, otherwise returns `False`. +pub trait IsLessOrEqual<Rhs = Self> { + /// The type representing either `True` or `False` + type Output: Bit; + /// Method returning `True` or `False`. + fn is_less_or_equal(self, rhs: Rhs) -> Self::Output; +} + +use crate::private::IsLessOrEqualPrivate; +impl<A, B> IsLessOrEqual<B> for A +where + A: Cmp<B> + IsLessOrEqualPrivate<B, Compare<A, B>>, +{ + type Output = <A as IsLessOrEqualPrivate<B, Compare<A, B>>>::Output; + + #[inline] + fn is_less_or_equal(self, rhs: B) -> Self::Output { + let lhs_cmp_rhs = self.compare::<Internal>(&rhs); + self.is_less_or_equal_private(rhs, lhs_cmp_rhs) + } +} + +/// A **type operator** that returns `True` if `Self != Rhs`, otherwise returns `False`. +pub trait IsNotEqual<Rhs = Self> { + /// The type representing either `True` or `False` + type Output: Bit; + /// Method returning `True` or `False`. + fn is_not_equal(self, rhs: Rhs) -> Self::Output; +} + +use crate::private::IsNotEqualPrivate; +impl<A, B> IsNotEqual<B> for A +where + A: Cmp<B> + IsNotEqualPrivate<B, Compare<A, B>>, +{ + type Output = <A as IsNotEqualPrivate<B, Compare<A, B>>>::Output; + + #[inline] + fn is_not_equal(self, rhs: B) -> Self::Output { + let lhs_cmp_rhs = self.compare::<Internal>(&rhs); + self.is_not_equal_private(rhs, lhs_cmp_rhs) + } +} + +/// A **type operator** that returns `True` if `Self >= Rhs`, otherwise returns `False`. +pub trait IsGreaterOrEqual<Rhs = Self> { + /// The type representing either `True` or `False` + type Output: Bit; + /// Method returning `True` or `False`. + fn is_greater_or_equal(self, rhs: Rhs) -> Self::Output; +} + +use crate::private::IsGreaterOrEqualPrivate; +impl<A, B> IsGreaterOrEqual<B> for A +where + A: Cmp<B> + IsGreaterOrEqualPrivate<B, Compare<A, B>>, +{ + type Output = <A as IsGreaterOrEqualPrivate<B, Compare<A, B>>>::Output; + + #[inline] + fn is_greater_or_equal(self, rhs: B) -> Self::Output { + let lhs_cmp_rhs = self.compare::<Internal>(&rhs); + self.is_greater_or_equal_private(rhs, lhs_cmp_rhs) + } +} + +/** +A convenience macro for comparing type numbers. Use `op!` instead. + +Due to the intricacies of the macro system, if the left-hand operand is more complex than a simple +`ident`, you must place a comma between it and the comparison sign. + +For example, you can do `cmp!(P5 > P3)` or `cmp!(typenum::P5, > typenum::P3)` but not +`cmp!(typenum::P5 > typenum::P3)`. + +The result of this comparison will always be one of `True` (aka `B1`) or `False` (aka `B0`). + +# Example +```rust +#[macro_use] extern crate typenum; +use typenum::consts::*; +use typenum::Bit; + +fn main() { +type Result = cmp!(P9 == op!(P1 + P2 * (P2 - N2))); +assert_eq!(Result::to_bool(), true); +} +``` + */ +#[deprecated(since = "1.9.0", note = "use the `op!` macro instead")] +#[macro_export] +macro_rules! cmp { + ($a:ident < $b:ty) => { + <$a as $crate::IsLess<$b>>::Output + }; + ($a:ty, < $b:ty) => { + <$a as $crate::IsLess<$b>>::Output + }; + + ($a:ident == $b:ty) => { + <$a as $crate::IsEqual<$b>>::Output + }; + ($a:ty, == $b:ty) => { + <$a as $crate::IsEqual<$b>>::Output + }; + + ($a:ident > $b:ty) => { + <$a as $crate::IsGreater<$b>>::Output + }; + ($a:ty, > $b:ty) => { + <$a as $crate::IsGreater<$b>>::Output + }; + + ($a:ident <= $b:ty) => { + <$a as $crate::IsLessOrEqual<$b>>::Output + }; + ($a:ty, <= $b:ty) => { + <$a as $crate::IsLessOrEqual<$b>>::Output + }; + + ($a:ident != $b:ty) => { + <$a as $crate::IsNotEqual<$b>>::Output + }; + ($a:ty, != $b:ty) => { + <$a as $crate::IsNotEqual<$b>>::Output + }; + + ($a:ident >= $b:ty) => { + <$a as $crate::IsGreaterOrEqual<$b>>::Output + }; + ($a:ty, >= $b:ty) => { + <$a as $crate::IsGreaterOrEqual<$b>>::Output + }; +} + +/// A **type operator** for taking the integer square root of `Self`. +/// +/// The integer square root of `n` is the largest integer `m` such +/// that `n >= m*m`. This definition is equivalent to truncating the +/// real-valued square root: `floor(real_sqrt(n))`. +pub trait SquareRoot { + /// The result of the integer square root. + type Output; +} + +/// A **type operator** for taking the integer binary logarithm of `Self`. +/// +/// The integer binary logarighm of `n` is the largest integer `m` such +/// that `n >= 2^m`. This definition is equivalent to truncating the +/// real-valued binary logarithm: `floor(log2(n))`. +pub trait Logarithm2 { + /// The result of the integer binary logarithm. + type Output; +} + +/// A **type operator** that computes the [greatest common divisor][gcd] of `Self` and `Rhs`. +/// +/// [gcd]: https://en.wikipedia.org/wiki/Greatest_common_divisor +/// +/// # Example +/// +/// ```rust +/// use typenum::{Gcd, Unsigned, U12, U8}; +/// +/// assert_eq!(<U12 as Gcd<U8>>::Output::to_i32(), 4); +/// ``` +pub trait Gcd<Rhs> { + /// The greatest common divisor. + type Output; +} + +/// A **type operator** for taking a concrete integer value from a type. +/// +/// It returns arbitrary integer value without explicitly specifying the +/// type. It is useful when you pass the values to methods that accept +/// distinct types without runtime casting. +pub trait ToInt<T> { + /// Method returning the concrete value for the type. + fn to_int() -> T; + /// The concrete value for the type. Can be used in `const` contexts. + const INT: T; +} diff --git a/third_party/rust/typenum/src/uint.rs b/third_party/rust/typenum/src/uint.rs new file mode 100644 index 0000000000..28ace5becb --- /dev/null +++ b/third_party/rust/typenum/src/uint.rs @@ -0,0 +1,2663 @@ +//! Type-level unsigned integers. +//! +//! +//! **Type operators** implemented: +//! +//! From `::core::ops`: `BitAnd`, `BitOr`, `BitXor`, `Shl`, `Shr`, `Add`, `Sub`, +//! `Mul`, `Div`, and `Rem`. +//! From `typenum`: `Same`, `Cmp`, and `Pow`. +//! +//! Rather than directly using the structs defined in this module, it is recommended that +//! you import and use the relevant aliases from the [consts](../consts/index.html) module. +//! +//! # Example +//! ```rust +//! use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Rem, Shl, Shr, Sub}; +//! use typenum::{Unsigned, U1, U2, U3, U4}; +//! +//! assert_eq!(<U3 as BitAnd<U2>>::Output::to_u32(), 2); +//! assert_eq!(<U3 as BitOr<U4>>::Output::to_u32(), 7); +//! assert_eq!(<U3 as BitXor<U2>>::Output::to_u32(), 1); +//! assert_eq!(<U3 as Shl<U1>>::Output::to_u32(), 6); +//! assert_eq!(<U3 as Shr<U1>>::Output::to_u32(), 1); +//! assert_eq!(<U3 as Add<U2>>::Output::to_u32(), 5); +//! assert_eq!(<U3 as Sub<U2>>::Output::to_u32(), 1); +//! assert_eq!(<U3 as Mul<U2>>::Output::to_u32(), 6); +//! assert_eq!(<U3 as Div<U2>>::Output::to_u32(), 1); +//! assert_eq!(<U3 as Rem<U2>>::Output::to_u32(), 1); +//! ``` + +use crate::{ + bit::{Bit, B0, B1}, + consts::{U0, U1}, + private::{ + BitDiff, BitDiffOut, Internal, InternalMarker, PrivateAnd, PrivateAndOut, PrivateCmp, + PrivateCmpOut, PrivateLogarithm2, PrivatePow, PrivatePowOut, PrivateSquareRoot, PrivateSub, + PrivateSubOut, PrivateXor, PrivateXorOut, Trim, TrimOut, + }, + Add1, Cmp, Double, Equal, Gcd, Gcf, GrEq, Greater, IsGreaterOrEqual, Len, Length, Less, Log2, + Logarithm2, Maximum, Minimum, NonZero, Or, Ord, Pow, Prod, Shleft, Shright, Sqrt, Square, + SquareRoot, Sub1, Sum, ToInt, Zero, +}; +use core::ops::{Add, BitAnd, BitOr, BitXor, Mul, Shl, Shr, Sub}; + +pub use crate::marker_traits::{PowerOfTwo, Unsigned}; + +/// The terminating type for `UInt`; it always comes after the most significant +/// bit. `UTerm` by itself represents zero, which is aliased to `U0`. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct UTerm; + +impl UTerm { + /// Instantiates a singleton representing this unsigned integer. + #[inline] + pub fn new() -> UTerm { + UTerm + } +} + +impl Unsigned for UTerm { + const U8: u8 = 0; + const U16: u16 = 0; + const U32: u32 = 0; + const U64: u64 = 0; + #[cfg(feature = "i128")] + const U128: u128 = 0; + const USIZE: usize = 0; + + const I8: i8 = 0; + const I16: i16 = 0; + const I32: i32 = 0; + const I64: i64 = 0; + #[cfg(feature = "i128")] + const I128: i128 = 0; + const ISIZE: isize = 0; + + #[inline] + fn to_u8() -> u8 { + 0 + } + #[inline] + fn to_u16() -> u16 { + 0 + } + #[inline] + fn to_u32() -> u32 { + 0 + } + #[inline] + fn to_u64() -> u64 { + 0 + } + #[cfg(feature = "i128")] + #[inline] + fn to_u128() -> u128 { + 0 + } + #[inline] + fn to_usize() -> usize { + 0 + } + + #[inline] + fn to_i8() -> i8 { + 0 + } + #[inline] + fn to_i16() -> i16 { + 0 + } + #[inline] + fn to_i32() -> i32 { + 0 + } + #[inline] + fn to_i64() -> i64 { + 0 + } + #[cfg(feature = "i128")] + #[inline] + fn to_i128() -> i128 { + 0 + } + #[inline] + fn to_isize() -> isize { + 0 + } +} + +/// `UInt` is defined recursively, where `B` is the least significant bit and `U` is the rest +/// of the number. Conceptually, `U` should be bound by the trait `Unsigned` and `B` should +/// be bound by the trait `Bit`, but enforcing these bounds causes linear instead of +/// logrithmic scaling in some places, so they are left off for now. They may be enforced in +/// future. +/// +/// In order to keep numbers unique, leading zeros are not allowed, so `UInt<UTerm, B0>` is +/// forbidden. +/// +/// # Example +/// ```rust +/// use typenum::{UInt, UTerm, B0, B1}; +/// +/// # #[allow(dead_code)] +/// type U6 = UInt<UInt<UInt<UTerm, B1>, B1>, B0>; +/// ``` +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] +pub struct UInt<U, B> { + /// The more significant bits of `Self`. + pub(crate) msb: U, + /// The least significant bit of `Self`. + pub(crate) lsb: B, +} + +impl<U: Unsigned, B: Bit> UInt<U, B> { + /// Instantiates a singleton representing this unsigned integer. + #[inline] + pub fn new() -> UInt<U, B> { + UInt::default() + } +} + +impl<U: Unsigned, B: Bit> Unsigned for UInt<U, B> { + const U8: u8 = B::U8 | U::U8 << 1; + const U16: u16 = B::U8 as u16 | U::U16 << 1; + const U32: u32 = B::U8 as u32 | U::U32 << 1; + const U64: u64 = B::U8 as u64 | U::U64 << 1; + #[cfg(feature = "i128")] + const U128: u128 = B::U8 as u128 | U::U128 << 1; + const USIZE: usize = B::U8 as usize | U::USIZE << 1; + + const I8: i8 = B::U8 as i8 | U::I8 << 1; + const I16: i16 = B::U8 as i16 | U::I16 << 1; + const I32: i32 = B::U8 as i32 | U::I32 << 1; + const I64: i64 = B::U8 as i64 | U::I64 << 1; + #[cfg(feature = "i128")] + const I128: i128 = B::U8 as i128 | U::I128 << 1; + const ISIZE: isize = B::U8 as isize | U::ISIZE << 1; + + #[inline] + fn to_u8() -> u8 { + B::to_u8() | U::to_u8() << 1 + } + #[inline] + fn to_u16() -> u16 { + u16::from(B::to_u8()) | U::to_u16() << 1 + } + #[inline] + fn to_u32() -> u32 { + u32::from(B::to_u8()) | U::to_u32() << 1 + } + #[inline] + fn to_u64() -> u64 { + u64::from(B::to_u8()) | U::to_u64() << 1 + } + #[cfg(feature = "i128")] + #[inline] + fn to_u128() -> u128 { + u128::from(B::to_u8()) | U::to_u128() << 1 + } + #[inline] + fn to_usize() -> usize { + usize::from(B::to_u8()) | U::to_usize() << 1 + } + + #[inline] + fn to_i8() -> i8 { + B::to_u8() as i8 | U::to_i8() << 1 + } + #[inline] + fn to_i16() -> i16 { + i16::from(B::to_u8()) | U::to_i16() << 1 + } + #[inline] + fn to_i32() -> i32 { + i32::from(B::to_u8()) | U::to_i32() << 1 + } + #[inline] + fn to_i64() -> i64 { + i64::from(B::to_u8()) | U::to_i64() << 1 + } + #[cfg(feature = "i128")] + #[inline] + fn to_i128() -> i128 { + i128::from(B::to_u8()) | U::to_i128() << 1 + } + #[inline] + fn to_isize() -> isize { + B::to_u8() as isize | U::to_isize() << 1 + } +} + +impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {} +impl Zero for UTerm {} + +impl PowerOfTwo for UInt<UTerm, B1> {} +impl<U: Unsigned + PowerOfTwo> PowerOfTwo for UInt<U, B0> {} + +// --------------------------------------------------------------------------------------- +// Getting length of unsigned integers, which is defined as the number of bits before `UTerm` + +/// Length of `UTerm` by itself is 0 +impl Len for UTerm { + type Output = U0; + #[inline] + fn len(&self) -> Self::Output { + UTerm + } +} + +/// Length of a bit is 1 +impl<U: Unsigned, B: Bit> Len for UInt<U, B> +where + U: Len, + Length<U>: Add<B1>, + Add1<Length<U>>: Unsigned, +{ + type Output = Add1<Length<U>>; + #[inline] + fn len(&self) -> Self::Output { + self.msb.len() + B1 + } +} + +// --------------------------------------------------------------------------------------- +// Adding bits to unsigned integers + +/// `UTerm + B0 = UTerm` +impl Add<B0> for UTerm { + type Output = UTerm; + #[inline] + fn add(self, _: B0) -> Self::Output { + UTerm + } +} + +/// `U + B0 = U` +impl<U: Unsigned, B: Bit> Add<B0> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn add(self, _: B0) -> Self::Output { + UInt::new() + } +} + +/// `UTerm + B1 = UInt<UTerm, B1>` +impl Add<B1> for UTerm { + type Output = UInt<UTerm, B1>; + #[inline] + fn add(self, _: B1) -> Self::Output { + UInt::new() + } +} + +/// `UInt<U, B0> + B1 = UInt<U + B1>` +impl<U: Unsigned> Add<B1> for UInt<U, B0> { + type Output = UInt<U, B1>; + #[inline] + fn add(self, _: B1) -> Self::Output { + UInt::new() + } +} + +/// `UInt<U, B1> + B1 = UInt<U + B1, B0>` +impl<U: Unsigned> Add<B1> for UInt<U, B1> +where + U: Add<B1>, + Add1<U>: Unsigned, +{ + type Output = UInt<Add1<U>, B0>; + #[inline] + fn add(self, _: B1) -> Self::Output { + UInt::new() + } +} + +// --------------------------------------------------------------------------------------- +// Adding unsigned integers + +/// `UTerm + U = U` +impl<U: Unsigned> Add<U> for UTerm { + type Output = U; + #[inline] + fn add(self, rhs: U) -> Self::Output { + rhs + } +} + +/// `UInt<U, B> + UTerm = UInt<U, B>` +impl<U: Unsigned, B: Bit> Add<UTerm> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn add(self, _: UTerm) -> Self::Output { + UInt::new() + } +} + +/// `UInt<Ul, B0> + UInt<Ur, B0> = UInt<Ul + Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B0>> for UInt<Ul, B0> +where + Ul: Add<Ur>, +{ + type Output = UInt<Sum<Ul, Ur>, B0>; + #[inline] + fn add(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb + rhs.msb, + lsb: B0, + } + } +} + +/// `UInt<Ul, B0> + UInt<Ur, B1> = UInt<Ul + Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B1>> for UInt<Ul, B0> +where + Ul: Add<Ur>, +{ + type Output = UInt<Sum<Ul, Ur>, B1>; + #[inline] + fn add(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb + rhs.msb, + lsb: B1, + } + } +} + +/// `UInt<Ul, B1> + UInt<Ur, B0> = UInt<Ul + Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B0>> for UInt<Ul, B1> +where + Ul: Add<Ur>, +{ + type Output = UInt<Sum<Ul, Ur>, B1>; + #[inline] + fn add(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb + rhs.msb, + lsb: B1, + } + } +} + +/// `UInt<Ul, B1> + UInt<Ur, B1> = UInt<(Ul + Ur) + B1, B0>` +impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B1>> for UInt<Ul, B1> +where + Ul: Add<Ur>, + Sum<Ul, Ur>: Add<B1>, +{ + type Output = UInt<Add1<Sum<Ul, Ur>>, B0>; + #[inline] + fn add(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb + rhs.msb + B1, + lsb: B0, + } + } +} + +// --------------------------------------------------------------------------------------- +// Subtracting bits from unsigned integers + +/// `UTerm - B0 = Term` +impl Sub<B0> for UTerm { + type Output = UTerm; + #[inline] + fn sub(self, _: B0) -> Self::Output { + UTerm + } +} + +/// `UInt - B0 = UInt` +impl<U: Unsigned, B: Bit> Sub<B0> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn sub(self, _: B0) -> Self::Output { + UInt::new() + } +} + +/// `UInt<U, B1> - B1 = UInt<U, B0>` +impl<U: Unsigned, B: Bit> Sub<B1> for UInt<UInt<U, B>, B1> { + type Output = UInt<UInt<U, B>, B0>; + #[inline] + fn sub(self, _: B1) -> Self::Output { + UInt::new() + } +} + +/// `UInt<UTerm, B1> - B1 = UTerm` +impl Sub<B1> for UInt<UTerm, B1> { + type Output = UTerm; + #[inline] + fn sub(self, _: B1) -> Self::Output { + UTerm + } +} + +/// `UInt<U, B0> - B1 = UInt<U - B1, B1>` +impl<U: Unsigned> Sub<B1> for UInt<U, B0> +where + U: Sub<B1>, + Sub1<U>: Unsigned, +{ + type Output = UInt<Sub1<U>, B1>; + #[inline] + fn sub(self, _: B1) -> Self::Output { + UInt::new() + } +} + +// --------------------------------------------------------------------------------------- +// Subtracting unsigned integers + +/// `UTerm - UTerm = UTerm` +impl Sub<UTerm> for UTerm { + type Output = UTerm; + #[inline] + fn sub(self, _: UTerm) -> Self::Output { + UTerm + } +} + +/// Subtracting unsigned integers. We just do our `PrivateSub` and then `Trim` the output. +impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned> Sub<Ur> for UInt<Ul, Bl> +where + UInt<Ul, Bl>: PrivateSub<Ur>, + PrivateSubOut<UInt<Ul, Bl>, Ur>: Trim, +{ + type Output = TrimOut<PrivateSubOut<UInt<Ul, Bl>, Ur>>; + #[inline] + fn sub(self, rhs: Ur) -> Self::Output { + self.private_sub(rhs).trim() + } +} + +/// `U - UTerm = U` +impl<U: Unsigned> PrivateSub<UTerm> for U { + type Output = U; + + #[inline] + fn private_sub(self, _: UTerm) -> Self::Output { + self + } +} + +/// `UInt<Ul, B0> - UInt<Ur, B0> = UInt<Ul - Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B0>> for UInt<Ul, B0> +where + Ul: PrivateSub<Ur>, +{ + type Output = UInt<PrivateSubOut<Ul, Ur>, B0>; + + #[inline] + fn private_sub(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.private_sub(rhs.msb), + lsb: B0, + } + } +} + +/// `UInt<Ul, B0> - UInt<Ur, B1> = UInt<(Ul - Ur) - B1, B1>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B1>> for UInt<Ul, B0> +where + Ul: PrivateSub<Ur>, + PrivateSubOut<Ul, Ur>: Sub<B1>, +{ + type Output = UInt<Sub1<PrivateSubOut<Ul, Ur>>, B1>; + + #[inline] + fn private_sub(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.private_sub(rhs.msb) - B1, + lsb: B1, + } + } +} + +/// `UInt<Ul, B1> - UInt<Ur, B0> = UInt<Ul - Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B0>> for UInt<Ul, B1> +where + Ul: PrivateSub<Ur>, +{ + type Output = UInt<PrivateSubOut<Ul, Ur>, B1>; + + #[inline] + fn private_sub(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.private_sub(rhs.msb), + lsb: B1, + } + } +} + +/// `UInt<Ul, B1> - UInt<Ur, B1> = UInt<Ul - Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B1>> for UInt<Ul, B1> +where + Ul: PrivateSub<Ur>, +{ + type Output = UInt<PrivateSubOut<Ul, Ur>, B0>; + + #[inline] + fn private_sub(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.private_sub(rhs.msb), + lsb: B0, + } + } +} + +// --------------------------------------------------------------------------------------- +// And unsigned integers + +/// 0 & X = 0 +impl<Ur: Unsigned> BitAnd<Ur> for UTerm { + type Output = UTerm; + #[inline] + fn bitand(self, _: Ur) -> Self::Output { + UTerm + } +} + +/// Anding unsigned integers. +/// We use our `PrivateAnd` operator and then `Trim` the output. +impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned> BitAnd<Ur> for UInt<Ul, Bl> +where + UInt<Ul, Bl>: PrivateAnd<Ur>, + PrivateAndOut<UInt<Ul, Bl>, Ur>: Trim, +{ + type Output = TrimOut<PrivateAndOut<UInt<Ul, Bl>, Ur>>; + #[inline] + fn bitand(self, rhs: Ur) -> Self::Output { + self.private_and(rhs).trim() + } +} + +/// `UTerm & X = UTerm` +impl<U: Unsigned> PrivateAnd<U> for UTerm { + type Output = UTerm; + + #[inline] + fn private_and(self, _: U) -> Self::Output { + UTerm + } +} + +/// `X & UTerm = UTerm` +impl<B: Bit, U: Unsigned> PrivateAnd<UTerm> for UInt<U, B> { + type Output = UTerm; + + #[inline] + fn private_and(self, _: UTerm) -> Self::Output { + UTerm + } +} + +/// `UInt<Ul, B0> & UInt<Ur, B0> = UInt<Ul & Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B0>> for UInt<Ul, B0> +where + Ul: PrivateAnd<Ur>, +{ + type Output = UInt<PrivateAndOut<Ul, Ur>, B0>; + + #[inline] + fn private_and(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.private_and(rhs.msb), + lsb: B0, + } + } +} + +/// `UInt<Ul, B0> & UInt<Ur, B1> = UInt<Ul & Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B1>> for UInt<Ul, B0> +where + Ul: PrivateAnd<Ur>, +{ + type Output = UInt<PrivateAndOut<Ul, Ur>, B0>; + + #[inline] + fn private_and(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.private_and(rhs.msb), + lsb: B0, + } + } +} + +/// `UInt<Ul, B1> & UInt<Ur, B0> = UInt<Ul & Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B0>> for UInt<Ul, B1> +where + Ul: PrivateAnd<Ur>, +{ + type Output = UInt<PrivateAndOut<Ul, Ur>, B0>; + + #[inline] + fn private_and(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.private_and(rhs.msb), + lsb: B0, + } + } +} + +/// `UInt<Ul, B1> & UInt<Ur, B1> = UInt<Ul & Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B1>> for UInt<Ul, B1> +where + Ul: PrivateAnd<Ur>, +{ + type Output = UInt<PrivateAndOut<Ul, Ur>, B1>; + + #[inline] + fn private_and(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.private_and(rhs.msb), + lsb: B1, + } + } +} + +// --------------------------------------------------------------------------------------- +// Or unsigned integers + +/// `UTerm | X = X` +impl<U: Unsigned> BitOr<U> for UTerm { + type Output = U; + #[inline] + fn bitor(self, rhs: U) -> Self::Output { + rhs + } +} + +/// `X | UTerm = X` +impl<B: Bit, U: Unsigned> BitOr<UTerm> for UInt<U, B> { + type Output = Self; + #[inline] + fn bitor(self, _: UTerm) -> Self::Output { + UInt::new() + } +} + +/// `UInt<Ul, B0> | UInt<Ur, B0> = UInt<Ul | Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B0>> for UInt<Ul, B0> +where + Ul: BitOr<Ur>, +{ + type Output = UInt<<Ul as BitOr<Ur>>::Output, B0>; + #[inline] + fn bitor(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.bitor(rhs.msb), + lsb: B0, + } + } +} + +/// `UInt<Ul, B0> | UInt<Ur, B1> = UInt<Ul | Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B1>> for UInt<Ul, B0> +where + Ul: BitOr<Ur>, +{ + type Output = UInt<Or<Ul, Ur>, B1>; + #[inline] + fn bitor(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.bitor(rhs.msb), + lsb: self.lsb.bitor(rhs.lsb), + } + } +} + +/// `UInt<Ul, B1> | UInt<Ur, B0> = UInt<Ul | Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B0>> for UInt<Ul, B1> +where + Ul: BitOr<Ur>, +{ + type Output = UInt<Or<Ul, Ur>, B1>; + #[inline] + fn bitor(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.bitor(rhs.msb), + lsb: self.lsb.bitor(rhs.lsb), + } + } +} + +/// `UInt<Ul, B1> | UInt<Ur, B1> = UInt<Ul | Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B1>> for UInt<Ul, B1> +where + Ul: BitOr<Ur>, +{ + type Output = UInt<Or<Ul, Ur>, B1>; + #[inline] + fn bitor(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.bitor(rhs.msb), + lsb: self.lsb.bitor(rhs.lsb), + } + } +} + +// --------------------------------------------------------------------------------------- +// Xor unsigned integers + +/// 0 ^ X = X +impl<Ur: Unsigned> BitXor<Ur> for UTerm { + type Output = Ur; + #[inline] + fn bitxor(self, rhs: Ur) -> Self::Output { + rhs + } +} + +/// Xoring unsigned integers. +/// We use our `PrivateXor` operator and then `Trim` the output. +impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned> BitXor<Ur> for UInt<Ul, Bl> +where + UInt<Ul, Bl>: PrivateXor<Ur>, + PrivateXorOut<UInt<Ul, Bl>, Ur>: Trim, +{ + type Output = TrimOut<PrivateXorOut<UInt<Ul, Bl>, Ur>>; + #[inline] + fn bitxor(self, rhs: Ur) -> Self::Output { + self.private_xor(rhs).trim() + } +} + +/// `UTerm ^ X = X` +impl<U: Unsigned> PrivateXor<U> for UTerm { + type Output = U; + + #[inline] + fn private_xor(self, rhs: U) -> Self::Output { + rhs + } +} + +/// `X ^ UTerm = X` +impl<B: Bit, U: Unsigned> PrivateXor<UTerm> for UInt<U, B> { + type Output = Self; + + #[inline] + fn private_xor(self, _: UTerm) -> Self::Output { + self + } +} + +/// `UInt<Ul, B0> ^ UInt<Ur, B0> = UInt<Ul ^ Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B0>> for UInt<Ul, B0> +where + Ul: PrivateXor<Ur>, +{ + type Output = UInt<PrivateXorOut<Ul, Ur>, B0>; + + #[inline] + fn private_xor(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.private_xor(rhs.msb), + lsb: B0, + } + } +} + +/// `UInt<Ul, B0> ^ UInt<Ur, B1> = UInt<Ul ^ Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B1>> for UInt<Ul, B0> +where + Ul: PrivateXor<Ur>, +{ + type Output = UInt<PrivateXorOut<Ul, Ur>, B1>; + + #[inline] + fn private_xor(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.private_xor(rhs.msb), + lsb: B1, + } + } +} + +/// `UInt<Ul, B1> ^ UInt<Ur, B0> = UInt<Ul ^ Ur, B1>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B0>> for UInt<Ul, B1> +where + Ul: PrivateXor<Ur>, +{ + type Output = UInt<PrivateXorOut<Ul, Ur>, B1>; + + #[inline] + fn private_xor(self, rhs: UInt<Ur, B0>) -> Self::Output { + UInt { + msb: self.msb.private_xor(rhs.msb), + lsb: B1, + } + } +} + +/// `UInt<Ul, B1> ^ UInt<Ur, B1> = UInt<Ul ^ Ur, B0>` +impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B1>> for UInt<Ul, B1> +where + Ul: PrivateXor<Ur>, +{ + type Output = UInt<PrivateXorOut<Ul, Ur>, B0>; + + #[inline] + fn private_xor(self, rhs: UInt<Ur, B1>) -> Self::Output { + UInt { + msb: self.msb.private_xor(rhs.msb), + lsb: B0, + } + } +} + +// --------------------------------------------------------------------------------------- +// Shl unsigned integers + +/// Shifting `UTerm` by a 0 bit: `UTerm << B0 = UTerm` +impl Shl<B0> for UTerm { + type Output = UTerm; + #[inline] + fn shl(self, _: B0) -> Self::Output { + UTerm + } +} + +/// Shifting `UTerm` by a 1 bit: `UTerm << B1 = UTerm` +impl Shl<B1> for UTerm { + type Output = UTerm; + #[inline] + fn shl(self, _: B1) -> Self::Output { + UTerm + } +} + +/// Shifting left any unsigned by a zero bit: `U << B0 = U` +impl<U: Unsigned, B: Bit> Shl<B0> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn shl(self, _: B0) -> Self::Output { + UInt::new() + } +} + +/// Shifting left a `UInt` by a one bit: `UInt<U, B> << B1 = UInt<UInt<U, B>, B0>` +impl<U: Unsigned, B: Bit> Shl<B1> for UInt<U, B> { + type Output = UInt<UInt<U, B>, B0>; + #[inline] + fn shl(self, _: B1) -> Self::Output { + UInt::new() + } +} + +/// Shifting left `UInt` by `UTerm`: `UInt<U, B> << UTerm = UInt<U, B>` +impl<U: Unsigned, B: Bit> Shl<UTerm> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn shl(self, _: UTerm) -> Self::Output { + UInt::new() + } +} + +/// Shifting left `UTerm` by an unsigned integer: `UTerm << U = UTerm` +impl<U: Unsigned> Shl<U> for UTerm { + type Output = UTerm; + #[inline] + fn shl(self, _: U) -> Self::Output { + UTerm + } +} + +/// Shifting left `UInt` by `UInt`: `X << Y` = `UInt(X, B0) << (Y - 1)` +impl<U: Unsigned, B: Bit, Ur: Unsigned, Br: Bit> Shl<UInt<Ur, Br>> for UInt<U, B> +where + UInt<Ur, Br>: Sub<B1>, + UInt<UInt<U, B>, B0>: Shl<Sub1<UInt<Ur, Br>>>, +{ + type Output = Shleft<UInt<UInt<U, B>, B0>, Sub1<UInt<Ur, Br>>>; + #[inline] + fn shl(self, rhs: UInt<Ur, Br>) -> Self::Output { + (UInt { msb: self, lsb: B0 }).shl(rhs - B1) + } +} + +// --------------------------------------------------------------------------------------- +// Shr unsigned integers + +/// Shifting right a `UTerm` by an unsigned integer: `UTerm >> U = UTerm` +impl<U: Unsigned> Shr<U> for UTerm { + type Output = UTerm; + #[inline] + fn shr(self, _: U) -> Self::Output { + UTerm + } +} + +/// Shifting right `UInt` by `UTerm`: `UInt<U, B> >> UTerm = UInt<U, B>` +impl<U: Unsigned, B: Bit> Shr<UTerm> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn shr(self, _: UTerm) -> Self::Output { + UInt::new() + } +} + +/// Shifting right `UTerm` by a 0 bit: `UTerm >> B0 = UTerm` +impl Shr<B0> for UTerm { + type Output = UTerm; + #[inline] + fn shr(self, _: B0) -> Self::Output { + UTerm + } +} + +/// Shifting right `UTerm` by a 1 bit: `UTerm >> B1 = UTerm` +impl Shr<B1> for UTerm { + type Output = UTerm; + #[inline] + fn shr(self, _: B1) -> Self::Output { + UTerm + } +} + +/// Shifting right any unsigned by a zero bit: `U >> B0 = U` +impl<U: Unsigned, B: Bit> Shr<B0> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn shr(self, _: B0) -> Self::Output { + UInt::new() + } +} + +/// Shifting right a `UInt` by a 1 bit: `UInt<U, B> >> B1 = U` +impl<U: Unsigned, B: Bit> Shr<B1> for UInt<U, B> { + type Output = U; + #[inline] + fn shr(self, _: B1) -> Self::Output { + self.msb + } +} + +/// Shifting right `UInt` by `UInt`: `UInt(U, B) >> Y` = `U >> (Y - 1)` +impl<U: Unsigned, B: Bit, Ur: Unsigned, Br: Bit> Shr<UInt<Ur, Br>> for UInt<U, B> +where + UInt<Ur, Br>: Sub<B1>, + U: Shr<Sub1<UInt<Ur, Br>>>, +{ + type Output = Shright<U, Sub1<UInt<Ur, Br>>>; + #[inline] + fn shr(self, rhs: UInt<Ur, Br>) -> Self::Output { + self.msb.shr(rhs - B1) + } +} + +// --------------------------------------------------------------------------------------- +// Multiply unsigned integers + +/// `UInt * B0 = UTerm` +impl<U: Unsigned, B: Bit> Mul<B0> for UInt<U, B> { + type Output = UTerm; + #[inline] + fn mul(self, _: B0) -> Self::Output { + UTerm + } +} + +/// `UTerm * B0 = UTerm` +impl Mul<B0> for UTerm { + type Output = UTerm; + #[inline] + fn mul(self, _: B0) -> Self::Output { + UTerm + } +} + +/// `UTerm * B1 = UTerm` +impl Mul<B1> for UTerm { + type Output = UTerm; + #[inline] + fn mul(self, _: B1) -> Self::Output { + UTerm + } +} + +/// `UInt * B1 = UInt` +impl<U: Unsigned, B: Bit> Mul<B1> for UInt<U, B> { + type Output = UInt<U, B>; + #[inline] + fn mul(self, _: B1) -> Self::Output { + UInt::new() + } +} + +/// `UInt<U, B> * UTerm = UTerm` +impl<U: Unsigned, B: Bit> Mul<UTerm> for UInt<U, B> { + type Output = UTerm; + #[inline] + fn mul(self, _: UTerm) -> Self::Output { + UTerm + } +} + +/// `UTerm * U = UTerm` +impl<U: Unsigned> Mul<U> for UTerm { + type Output = UTerm; + #[inline] + fn mul(self, _: U) -> Self::Output { + UTerm + } +} + +/// `UInt<Ul, B0> * UInt<Ur, B> = UInt<(Ul * UInt<Ur, B>), B0>` +impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B0> +where + Ul: Mul<UInt<Ur, B>>, +{ + type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>; + #[inline] + fn mul(self, rhs: UInt<Ur, B>) -> Self::Output { + UInt { + msb: self.msb * rhs, + lsb: B0, + } + } +} + +/// `UInt<Ul, B1> * UInt<Ur, B> = UInt<(Ul * UInt<Ur, B>), B0> + UInt<Ur, B>` +impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B1> +where + Ul: Mul<UInt<Ur, B>>, + UInt<Prod<Ul, UInt<Ur, B>>, B0>: Add<UInt<Ur, B>>, +{ + type Output = Sum<UInt<Prod<Ul, UInt<Ur, B>>, B0>, UInt<Ur, B>>; + #[inline] + fn mul(self, rhs: UInt<Ur, B>) -> Self::Output { + UInt { + msb: self.msb * rhs, + lsb: B0, + } + rhs + } +} + +// --------------------------------------------------------------------------------------- +// Compare unsigned integers + +/// Zero == Zero +impl Cmp<UTerm> for UTerm { + type Output = Equal; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &UTerm) -> Self::Output { + Equal + } +} + +/// Nonzero > Zero +impl<U: Unsigned, B: Bit> Cmp<UTerm> for UInt<U, B> { + type Output = Greater; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &UTerm) -> Self::Output { + Greater + } +} + +/// Zero < Nonzero +impl<U: Unsigned, B: Bit> Cmp<UInt<U, B>> for UTerm { + type Output = Less; + + #[inline] + fn compare<IM: InternalMarker>(&self, _: &UInt<U, B>) -> Self::Output { + Less + } +} + +/// `UInt<Ul, B0>` cmp with `UInt<Ur, B0>`: `SoFar` is `Equal` +impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B0>> for UInt<Ul, B0> +where + Ul: PrivateCmp<Ur, Equal>, +{ + type Output = PrivateCmpOut<Ul, Ur, Equal>; + + #[inline] + fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B0>) -> Self::Output { + self.msb.private_cmp(&rhs.msb, Equal) + } +} + +/// `UInt<Ul, B1>` cmp with `UInt<Ur, B1>`: `SoFar` is `Equal` +impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B1>> for UInt<Ul, B1> +where + Ul: PrivateCmp<Ur, Equal>, +{ + type Output = PrivateCmpOut<Ul, Ur, Equal>; + + #[inline] + fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B1>) -> Self::Output { + self.msb.private_cmp(&rhs.msb, Equal) + } +} + +/// `UInt<Ul, B0>` cmp with `UInt<Ur, B1>`: `SoFar` is `Less` +impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B1>> for UInt<Ul, B0> +where + Ul: PrivateCmp<Ur, Less>, +{ + type Output = PrivateCmpOut<Ul, Ur, Less>; + + #[inline] + fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B1>) -> Self::Output { + self.msb.private_cmp(&rhs.msb, Less) + } +} + +/// `UInt<Ul, B1>` cmp with `UInt<Ur, B0>`: `SoFar` is `Greater` +impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B0>> for UInt<Ul, B1> +where + Ul: PrivateCmp<Ur, Greater>, +{ + type Output = PrivateCmpOut<Ul, Ur, Greater>; + + #[inline] + fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B0>) -> Self::Output { + self.msb.private_cmp(&rhs.msb, Greater) + } +} + +/// Comparing non-terimal bits, with both having bit `B0`. +/// These are `Equal`, so we propogate `SoFar`. +impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B0>, SoFar> for UInt<Ul, B0> +where + Ul: Unsigned, + Ur: Unsigned, + SoFar: Ord, + Ul: PrivateCmp<Ur, SoFar>, +{ + type Output = PrivateCmpOut<Ul, Ur, SoFar>; + + #[inline] + fn private_cmp(&self, rhs: &UInt<Ur, B0>, so_far: SoFar) -> Self::Output { + self.msb.private_cmp(&rhs.msb, so_far) + } +} + +/// Comparing non-terimal bits, with both having bit `B1`. +/// These are `Equal`, so we propogate `SoFar`. +impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B1>, SoFar> for UInt<Ul, B1> +where + Ul: Unsigned, + Ur: Unsigned, + SoFar: Ord, + Ul: PrivateCmp<Ur, SoFar>, +{ + type Output = PrivateCmpOut<Ul, Ur, SoFar>; + + #[inline] + fn private_cmp(&self, rhs: &UInt<Ur, B1>, so_far: SoFar) -> Self::Output { + self.msb.private_cmp(&rhs.msb, so_far) + } +} + +/// Comparing non-terimal bits, with `Lhs` having bit `B0` and `Rhs` having bit `B1`. +/// `SoFar`, Lhs is `Less`. +impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B1>, SoFar> for UInt<Ul, B0> +where + Ul: Unsigned, + Ur: Unsigned, + SoFar: Ord, + Ul: PrivateCmp<Ur, Less>, +{ + type Output = PrivateCmpOut<Ul, Ur, Less>; + + #[inline] + fn private_cmp(&self, rhs: &UInt<Ur, B1>, _: SoFar) -> Self::Output { + self.msb.private_cmp(&rhs.msb, Less) + } +} + +/// Comparing non-terimal bits, with `Lhs` having bit `B1` and `Rhs` having bit `B0`. +/// `SoFar`, Lhs is `Greater`. +impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B0>, SoFar> for UInt<Ul, B1> +where + Ul: Unsigned, + Ur: Unsigned, + SoFar: Ord, + Ul: PrivateCmp<Ur, Greater>, +{ + type Output = PrivateCmpOut<Ul, Ur, Greater>; + + #[inline] + fn private_cmp(&self, rhs: &UInt<Ur, B0>, _: SoFar) -> Self::Output { + self.msb.private_cmp(&rhs.msb, Greater) + } +} + +/// Got to the end of just the `Lhs`. It's `Less`. +impl<U: Unsigned, B: Bit, SoFar: Ord> PrivateCmp<UInt<U, B>, SoFar> for UTerm { + type Output = Less; + + #[inline] + fn private_cmp(&self, _: &UInt<U, B>, _: SoFar) -> Self::Output { + Less + } +} + +/// Got to the end of just the `Rhs`. `Lhs` is `Greater`. +impl<U: Unsigned, B: Bit, SoFar: Ord> PrivateCmp<UTerm, SoFar> for UInt<U, B> { + type Output = Greater; + + #[inline] + fn private_cmp(&self, _: &UTerm, _: SoFar) -> Self::Output { + Greater + } +} + +/// Got to the end of both! Return `SoFar` +impl<SoFar: Ord> PrivateCmp<UTerm, SoFar> for UTerm { + type Output = SoFar; + + #[inline] + fn private_cmp(&self, _: &UTerm, so_far: SoFar) -> Self::Output { + so_far + } +} + +// --------------------------------------------------------------------------------------- +// Getting difference in number of bits + +impl<Ul, Bl, Ur, Br> BitDiff<UInt<Ur, Br>> for UInt<Ul, Bl> +where + Ul: Unsigned, + Bl: Bit, + Ur: Unsigned, + Br: Bit, + Ul: BitDiff<Ur>, +{ + type Output = BitDiffOut<Ul, Ur>; +} + +impl<Ul> BitDiff<UTerm> for Ul +where + Ul: Unsigned + Len, +{ + type Output = Length<Ul>; +} + +// --------------------------------------------------------------------------------------- +// Shifting one number until it's the size of another +use crate::private::ShiftDiff; +impl<Ul: Unsigned, Ur: Unsigned> ShiftDiff<Ur> for Ul +where + Ur: BitDiff<Ul>, + Ul: Shl<BitDiffOut<Ur, Ul>>, +{ + type Output = Shleft<Ul, BitDiffOut<Ur, Ul>>; +} + +// --------------------------------------------------------------------------------------- +// Powers of unsigned integers + +/// X^N +impl<X: Unsigned, N: Unsigned> Pow<N> for X +where + X: PrivatePow<U1, N>, +{ + type Output = PrivatePowOut<X, U1, N>; + #[inline] + fn powi(self, n: N) -> Self::Output { + self.private_pow(U1::new(), n) + } +} + +impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U0> for X { + type Output = Y; + + #[inline] + fn private_pow(self, y: Y, _: U0) -> Self::Output { + y + } +} + +impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U1> for X +where + X: Mul<Y>, +{ + type Output = Prod<X, Y>; + + #[inline] + fn private_pow(self, y: Y, _: U1) -> Self::Output { + self * y + } +} + +/// N is even +impl<Y: Unsigned, U: Unsigned, B: Bit, X: Unsigned> PrivatePow<Y, UInt<UInt<U, B>, B0>> for X +where + X: Mul, + Square<X>: PrivatePow<Y, UInt<U, B>>, +{ + type Output = PrivatePowOut<Square<X>, Y, UInt<U, B>>; + + #[inline] + fn private_pow(self, y: Y, n: UInt<UInt<U, B>, B0>) -> Self::Output { + (self * self).private_pow(y, n.msb) + } +} + +/// N is odd +impl<Y: Unsigned, U: Unsigned, B: Bit, X: Unsigned> PrivatePow<Y, UInt<UInt<U, B>, B1>> for X +where + X: Mul + Mul<Y>, + Square<X>: PrivatePow<Prod<X, Y>, UInt<U, B>>, +{ + type Output = PrivatePowOut<Square<X>, Prod<X, Y>, UInt<U, B>>; + + #[inline] + fn private_pow(self, y: Y, n: UInt<UInt<U, B>, B1>) -> Self::Output { + (self * self).private_pow(self * y, n.msb) + } +} + +//------------------------------------------ +// Greatest Common Divisor + +/// The even number 2*N +#[allow(unused)] // Silence spurious warning on older versions of rust +type Even<N> = UInt<N, B0>; + +/// The odd number 2*N + 1 +type Odd<N> = UInt<N, B1>; + +/// gcd(0, 0) = 0 +impl Gcd<U0> for U0 { + type Output = U0; +} + +/// gcd(x, 0) = x +impl<X> Gcd<U0> for X +where + X: Unsigned + NonZero, +{ + type Output = X; +} + +/// gcd(0, y) = y +impl<Y> Gcd<Y> for U0 +where + Y: Unsigned + NonZero, +{ + type Output = Y; +} + +/// gcd(x, y) = 2*gcd(x/2, y/2) if both x and y even +impl<Xp, Yp> Gcd<Even<Yp>> for Even<Xp> +where + Xp: Gcd<Yp>, + Even<Xp>: NonZero, + Even<Yp>: NonZero, +{ + type Output = UInt<Gcf<Xp, Yp>, B0>; +} + +/// gcd(x, y) = gcd(x, y/2) if x odd and y even +impl<Xp, Yp> Gcd<Even<Yp>> for Odd<Xp> +where + Odd<Xp>: Gcd<Yp>, + Even<Yp>: NonZero, +{ + type Output = Gcf<Odd<Xp>, Yp>; +} + +/// gcd(x, y) = gcd(x/2, y) if x even and y odd +impl<Xp, Yp> Gcd<Odd<Yp>> for Even<Xp> +where + Xp: Gcd<Odd<Yp>>, + Even<Xp>: NonZero, +{ + type Output = Gcf<Xp, Odd<Yp>>; +} + +/// gcd(x, y) = gcd([max(x, y) - min(x, y)], min(x, y)) if both x and y odd +/// +/// This will immediately invoke the case for x even and y odd because the difference of two odd +/// numbers is an even number. +impl<Xp, Yp> Gcd<Odd<Yp>> for Odd<Xp> +where + Odd<Xp>: Max<Odd<Yp>> + Min<Odd<Yp>>, + Odd<Yp>: Max<Odd<Xp>> + Min<Odd<Xp>>, + Maximum<Odd<Xp>, Odd<Yp>>: Sub<Minimum<Odd<Xp>, Odd<Yp>>>, + Diff<Maximum<Odd<Xp>, Odd<Yp>>, Minimum<Odd<Xp>, Odd<Yp>>>: Gcd<Minimum<Odd<Xp>, Odd<Yp>>>, +{ + type Output = + Gcf<Diff<Maximum<Odd<Xp>, Odd<Yp>>, Minimum<Odd<Xp>, Odd<Yp>>>, Minimum<Odd<Xp>, Odd<Yp>>>; +} + +#[cfg(test)] +mod gcd_tests { + use super::*; + use crate::consts::*; + + macro_rules! gcd_test { + ( + $( $a:ident, $b:ident => $c:ident ),* $(,)* + ) => { + $( + assert_eq!(<Gcf<$a, $b> as Unsigned>::to_usize(), $c::to_usize()); + assert_eq!(<Gcf<$b, $a> as Unsigned>::to_usize(), $c::to_usize()); + )* + } + } + + #[test] + fn gcd() { + gcd_test! { + U0, U0 => U0, + U0, U42 => U42, + U12, U8 => U4, + U13, U1013 => U1, // Two primes + U9, U26 => U1, // Not prime but coprime + U143, U273 => U13, + U117, U273 => U39, + } + } +} + +// ----------------------------------------- +// GetBit + +#[allow(missing_docs)] +pub trait GetBit<I> { + #[allow(missing_docs)] + type Output; + + #[doc(hidden)] + fn get_bit<IM: InternalMarker>(&self, _: &I) -> Self::Output; +} + +#[allow(missing_docs)] +pub type GetBitOut<N, I> = <N as GetBit<I>>::Output; + +// Base case +impl<Un, Bn> GetBit<U0> for UInt<Un, Bn> +where + Bn: Copy, +{ + type Output = Bn; + + #[inline] + fn get_bit<IM: InternalMarker>(&self, _: &U0) -> Self::Output { + self.lsb + } +} + +// Recursion case +impl<Un, Bn, Ui, Bi> GetBit<UInt<Ui, Bi>> for UInt<Un, Bn> +where + UInt<Ui, Bi>: Copy + Sub<B1>, + Un: GetBit<Sub1<UInt<Ui, Bi>>>, +{ + type Output = GetBitOut<Un, Sub1<UInt<Ui, Bi>>>; + + #[inline] + fn get_bit<IM: InternalMarker>(&self, i: &UInt<Ui, Bi>) -> Self::Output { + self.msb.get_bit::<Internal>(&(*i - B1)) + } +} + +// Ran out of bits +impl<I> GetBit<I> for UTerm { + type Output = B0; + + #[inline] + fn get_bit<IM: InternalMarker>(&self, _: &I) -> Self::Output { + B0 + } +} + +#[test] +fn test_get_bit() { + use crate::consts::*; + use crate::Same; + type T1 = <GetBitOut<U2, U0> as Same<B0>>::Output; + type T2 = <GetBitOut<U2, U1> as Same<B1>>::Output; + type T3 = <GetBitOut<U2, U2> as Same<B0>>::Output; + + <T1 as Bit>::to_bool(); + <T2 as Bit>::to_bool(); + <T3 as Bit>::to_bool(); +} + +// ----------------------------------------- +// SetBit + +/// A **type operator** that, when implemented for unsigned integer `N`, sets the bit at position +/// `I` to `B`. +pub trait SetBit<I, B> { + #[allow(missing_docs)] + type Output; + + #[doc(hidden)] + fn set_bit<IM: InternalMarker>(self, _: I, _: B) -> Self::Output; +} +/// Alias for the result of calling `SetBit`: `SetBitOut<N, I, B> = <N as SetBit<I, B>>::Output`. +pub type SetBitOut<N, I, B> = <N as SetBit<I, B>>::Output; + +use crate::private::{PrivateSetBit, PrivateSetBitOut}; + +// Call private one then trim it +impl<N, I, B> SetBit<I, B> for N +where + N: PrivateSetBit<I, B>, + PrivateSetBitOut<N, I, B>: Trim, +{ + type Output = TrimOut<PrivateSetBitOut<N, I, B>>; + + #[inline] + fn set_bit<IM: InternalMarker>(self, i: I, b: B) -> Self::Output { + self.private_set_bit(i, b).trim() + } +} + +// Base case +impl<Un, Bn, B> PrivateSetBit<U0, B> for UInt<Un, Bn> { + type Output = UInt<Un, B>; + + #[inline] + fn private_set_bit(self, _: U0, b: B) -> Self::Output { + UInt { + msb: self.msb, + lsb: b, + } + } +} + +// Recursion case +impl<Un, Bn, Ui, Bi, B> PrivateSetBit<UInt<Ui, Bi>, B> for UInt<Un, Bn> +where + UInt<Ui, Bi>: Sub<B1>, + Un: PrivateSetBit<Sub1<UInt<Ui, Bi>>, B>, +{ + type Output = UInt<PrivateSetBitOut<Un, Sub1<UInt<Ui, Bi>>, B>, Bn>; + + #[inline] + fn private_set_bit(self, i: UInt<Ui, Bi>, b: B) -> Self::Output { + UInt { + msb: self.msb.private_set_bit(i - B1, b), + lsb: self.lsb, + } + } +} + +// Ran out of bits, setting B0 +impl<I> PrivateSetBit<I, B0> for UTerm { + type Output = UTerm; + + #[inline] + fn private_set_bit(self, _: I, _: B0) -> Self::Output { + UTerm + } +} + +// Ran out of bits, setting B1 +impl<I> PrivateSetBit<I, B1> for UTerm +where + U1: Shl<I>, +{ + type Output = Shleft<U1, I>; + + #[inline] + fn private_set_bit(self, i: I, _: B1) -> Self::Output { + <U1 as Shl<I>>::shl(U1::new(), i) + } +} + +#[test] +fn test_set_bit() { + use crate::consts::*; + use crate::Same; + type T1 = <SetBitOut<U2, U0, B0> as Same<U2>>::Output; + type T2 = <SetBitOut<U2, U0, B1> as Same<U3>>::Output; + type T3 = <SetBitOut<U2, U1, B0> as Same<U0>>::Output; + type T4 = <SetBitOut<U2, U1, B1> as Same<U2>>::Output; + type T5 = <SetBitOut<U2, U2, B0> as Same<U2>>::Output; + type T6 = <SetBitOut<U2, U2, B1> as Same<U6>>::Output; + type T7 = <SetBitOut<U2, U3, B0> as Same<U2>>::Output; + type T8 = <SetBitOut<U2, U3, B1> as Same<U10>>::Output; + type T9 = <SetBitOut<U2, U4, B0> as Same<U2>>::Output; + type T10 = <SetBitOut<U2, U4, B1> as Same<U18>>::Output; + + type T11 = <SetBitOut<U3, U0, B0> as Same<U2>>::Output; + + <T1 as Unsigned>::to_u32(); + <T2 as Unsigned>::to_u32(); + <T3 as Unsigned>::to_u32(); + <T4 as Unsigned>::to_u32(); + <T5 as Unsigned>::to_u32(); + <T6 as Unsigned>::to_u32(); + <T7 as Unsigned>::to_u32(); + <T8 as Unsigned>::to_u32(); + <T9 as Unsigned>::to_u32(); + <T10 as Unsigned>::to_u32(); + <T11 as Unsigned>::to_u32(); +} + +// ----------------------------------------- + +// Division algorithm: +// We have N / D: +// let Q = 0, R = 0 +// NBits = len(N) +// for I in NBits-1..0: +// R <<=1 +// R[0] = N[i] +// let C = R.cmp(D) +// if C == Equal or Greater: +// R -= D +// Q[i] = 1 + +#[cfg(tests)] +mod tests { + macro_rules! test_div { + ($a:ident / $b:ident = $c:ident) => {{ + type R = Quot<$a, $b>; + assert_eq!(<R as Unsigned>::to_usize(), $c::to_usize()); + }}; + } + #[test] + fn test_div() { + use crate::consts::*; + use crate::{Quot, Same}; + + test_div!(U0 / U1 = U0); + test_div!(U1 / U1 = U1); + test_div!(U2 / U1 = U2); + test_div!(U3 / U1 = U3); + test_div!(U4 / U1 = U4); + + test_div!(U0 / U2 = U0); + test_div!(U1 / U2 = U0); + test_div!(U2 / U2 = U1); + test_div!(U3 / U2 = U1); + test_div!(U4 / U2 = U2); + test_div!(U6 / U2 = U3); + test_div!(U7 / U2 = U3); + + type T = <SetBitOut<U0, U1, B1> as Same<U2>>::Output; + <T as Unsigned>::to_u32(); + } +} +// ----------------------------------------- +// Div +use core::ops::Div; + +// 0 // N +impl<Ur: Unsigned, Br: Bit> Div<UInt<Ur, Br>> for UTerm { + type Output = UTerm; + #[inline] + fn div(self, _: UInt<Ur, Br>) -> Self::Output { + UTerm + } +} + +// M // N +impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit> Div<UInt<Ur, Br>> for UInt<Ul, Bl> +where + UInt<Ul, Bl>: Len, + Length<UInt<Ul, Bl>>: Sub<B1>, + (): PrivateDiv<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>, +{ + type Output = PrivateDivQuot<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>; + #[inline] + #[cfg_attr(feature = "cargo-clippy", allow(clippy::suspicious_arithmetic_impl))] + fn div(self, rhs: UInt<Ur, Br>) -> Self::Output { + ().private_div_quotient(self, rhs, U0::new(), U0::new(), self.len() - B1) + } +} + +// ----------------------------------------- +// Rem +use core::ops::Rem; + +// 0 % N +impl<Ur: Unsigned, Br: Bit> Rem<UInt<Ur, Br>> for UTerm { + type Output = UTerm; + #[inline] + fn rem(self, _: UInt<Ur, Br>) -> Self::Output { + UTerm + } +} + +// M % N +impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit> Rem<UInt<Ur, Br>> for UInt<Ul, Bl> +where + UInt<Ul, Bl>: Len, + Length<UInt<Ul, Bl>>: Sub<B1>, + (): PrivateDiv<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>, +{ + type Output = PrivateDivRem<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>; + #[inline] + fn rem(self, rhs: UInt<Ur, Br>) -> Self::Output { + ().private_div_remainder(self, rhs, UTerm, UTerm, self.len() - B1) + } +} + +// ----------------------------------------- +// PrivateDiv +use crate::private::{PrivateDiv, PrivateDivQuot, PrivateDivRem}; + +use crate::Compare; +// R == 0: We set R = UInt<UTerm, N[i]>, then call out to PrivateDivIf for the if statement +impl<N, D, Q, I> PrivateDiv<N, D, Q, U0, I> for () +where + N: GetBit<I>, + UInt<UTerm, GetBitOut<N, I>>: Trim, + TrimOut<UInt<UTerm, GetBitOut<N, I>>>: Cmp<D>, + (): PrivateDivIf< + N, + D, + Q, + TrimOut<UInt<UTerm, GetBitOut<N, I>>>, + I, + Compare<TrimOut<UInt<UTerm, GetBitOut<N, I>>>, D>, + >, +{ + type Quotient = PrivateDivIfQuot< + N, + D, + Q, + TrimOut<UInt<UTerm, GetBitOut<N, I>>>, + I, + Compare<TrimOut<UInt<UTerm, GetBitOut<N, I>>>, D>, + >; + type Remainder = PrivateDivIfRem< + N, + D, + Q, + TrimOut<UInt<UTerm, GetBitOut<N, I>>>, + I, + Compare<TrimOut<UInt<UTerm, GetBitOut<N, I>>>, D>, + >; + + #[inline] + fn private_div_quotient(self, n: N, d: D, q: Q, _: U0, i: I) -> Self::Quotient +where { + let r = (UInt { + msb: UTerm, + lsb: n.get_bit::<Internal>(&i), + }) + .trim(); + let r_cmp_d = r.compare::<Internal>(&d); + ().private_div_if_quotient(n, d, q, r, i, r_cmp_d) + } + + #[inline] + fn private_div_remainder(self, n: N, d: D, q: Q, _: U0, i: I) -> Self::Remainder { + let r = (UInt { + msb: UTerm, + lsb: n.get_bit::<Internal>(&i), + }) + .trim(); + let r_cmp_d = r.compare::<Internal>(&d); + ().private_div_if_remainder(n, d, q, r, i, r_cmp_d) + } +} + +// R > 0: We perform R <<= 1 and R[0] = N[i], then call out to PrivateDivIf for the if statement +impl<N, D, Q, Ur, Br, I> PrivateDiv<N, D, Q, UInt<Ur, Br>, I> for () +where + N: GetBit<I>, + UInt<UInt<Ur, Br>, GetBitOut<N, I>>: Cmp<D>, + (): PrivateDivIf< + N, + D, + Q, + UInt<UInt<Ur, Br>, GetBitOut<N, I>>, + I, + Compare<UInt<UInt<Ur, Br>, GetBitOut<N, I>>, D>, + >, +{ + type Quotient = PrivateDivIfQuot< + N, + D, + Q, + UInt<UInt<Ur, Br>, GetBitOut<N, I>>, + I, + Compare<UInt<UInt<Ur, Br>, GetBitOut<N, I>>, D>, + >; + type Remainder = PrivateDivIfRem< + N, + D, + Q, + UInt<UInt<Ur, Br>, GetBitOut<N, I>>, + I, + Compare<UInt<UInt<Ur, Br>, GetBitOut<N, I>>, D>, + >; + + #[inline] + fn private_div_quotient(self, n: N, d: D, q: Q, r: UInt<Ur, Br>, i: I) -> Self::Quotient { + let r = UInt { + msb: r, + lsb: n.get_bit::<Internal>(&i), + }; + let r_cmp_d = r.compare::<Internal>(&d); + ().private_div_if_quotient(n, d, q, r, i, r_cmp_d) + } + + #[inline] + fn private_div_remainder(self, n: N, d: D, q: Q, r: UInt<Ur, Br>, i: I) -> Self::Remainder { + let r = UInt { + msb: r, + lsb: n.get_bit::<Internal>(&i), + }; + let r_cmp_d = r.compare::<Internal>(&d); + ().private_div_if_remainder(n, d, q, r, i, r_cmp_d) + } +} + +// ----------------------------------------- +// PrivateDivIf + +use crate::private::{PrivateDivIf, PrivateDivIfQuot, PrivateDivIfRem}; + +// R < D, I > 0, we do nothing and recurse +impl<N, D, Q, R, Ui, Bi> PrivateDivIf<N, D, Q, R, UInt<Ui, Bi>, Less> for () +where + UInt<Ui, Bi>: Sub<B1>, + (): PrivateDiv<N, D, Q, R, Sub1<UInt<Ui, Bi>>>, +{ + type Quotient = PrivateDivQuot<N, D, Q, R, Sub1<UInt<Ui, Bi>>>; + type Remainder = PrivateDivRem<N, D, Q, R, Sub1<UInt<Ui, Bi>>>; + + #[inline] + fn private_div_if_quotient( + self, + n: N, + d: D, + q: Q, + r: R, + i: UInt<Ui, Bi>, + _: Less, + ) -> Self::Quotient +where { + ().private_div_quotient(n, d, q, r, i - B1) + } + + #[inline] + fn private_div_if_remainder( + self, + n: N, + d: D, + q: Q, + r: R, + i: UInt<Ui, Bi>, + _: Less, + ) -> Self::Remainder +where { + ().private_div_remainder(n, d, q, r, i - B1) + } +} + +// R == D, I > 0, we set R = 0, Q[I] = 1 and recurse +impl<N, D, Q, R, Ui, Bi> PrivateDivIf<N, D, Q, R, UInt<Ui, Bi>, Equal> for () +where + UInt<Ui, Bi>: Copy + Sub<B1>, + Q: SetBit<UInt<Ui, Bi>, B1>, + (): PrivateDiv<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, U0, Sub1<UInt<Ui, Bi>>>, +{ + type Quotient = PrivateDivQuot<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, U0, Sub1<UInt<Ui, Bi>>>; + type Remainder = PrivateDivRem<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, U0, Sub1<UInt<Ui, Bi>>>; + + #[inline] + fn private_div_if_quotient( + self, + n: N, + d: D, + q: Q, + _: R, + i: UInt<Ui, Bi>, + _: Equal, + ) -> Self::Quotient +where { + ().private_div_quotient(n, d, q.set_bit::<Internal>(i, B1), U0::new(), i - B1) + } + + #[inline] + fn private_div_if_remainder( + self, + n: N, + d: D, + q: Q, + _: R, + i: UInt<Ui, Bi>, + _: Equal, + ) -> Self::Remainder +where { + ().private_div_remainder(n, d, q.set_bit::<Internal>(i, B1), U0::new(), i - B1) + } +} + +use crate::Diff; +// R > D, I > 0, we set R -= D, Q[I] = 1 and recurse +impl<N, D, Q, R, Ui, Bi> PrivateDivIf<N, D, Q, R, UInt<Ui, Bi>, Greater> for () +where + D: Copy, + UInt<Ui, Bi>: Copy + Sub<B1>, + R: Sub<D>, + Q: SetBit<UInt<Ui, Bi>, B1>, + (): PrivateDiv<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, Diff<R, D>, Sub1<UInt<Ui, Bi>>>, +{ + type Quotient = + PrivateDivQuot<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, Diff<R, D>, Sub1<UInt<Ui, Bi>>>; + type Remainder = + PrivateDivRem<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, Diff<R, D>, Sub1<UInt<Ui, Bi>>>; + + #[inline] + fn private_div_if_quotient( + self, + n: N, + d: D, + q: Q, + r: R, + i: UInt<Ui, Bi>, + _: Greater, + ) -> Self::Quotient +where { + ().private_div_quotient(n, d, q.set_bit::<Internal>(i, B1), r - d, i - B1) + } + + #[inline] + fn private_div_if_remainder( + self, + n: N, + d: D, + q: Q, + r: R, + i: UInt<Ui, Bi>, + _: Greater, + ) -> Self::Remainder +where { + ().private_div_remainder(n, d, q.set_bit::<Internal>(i, B1), r - d, i - B1) + } +} + +// R < D, I == 0: we do nothing, and return +impl<N, D, Q, R> PrivateDivIf<N, D, Q, R, U0, Less> for () { + type Quotient = Q; + type Remainder = R; + + #[inline] + fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, _: U0, _: Less) -> Self::Quotient { + q + } + + #[inline] + fn private_div_if_remainder(self, _: N, _: D, _: Q, r: R, _: U0, _: Less) -> Self::Remainder { + r + } +} + +// R == D, I == 0: we set R = 0, Q[I] = 1, and return +impl<N, D, Q, R> PrivateDivIf<N, D, Q, R, U0, Equal> for () +where + Q: SetBit<U0, B1>, +{ + type Quotient = SetBitOut<Q, U0, B1>; + type Remainder = U0; + + #[inline] + fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, i: U0, _: Equal) -> Self::Quotient { + q.set_bit::<Internal>(i, B1) + } + + #[inline] + fn private_div_if_remainder(self, _: N, _: D, _: Q, _: R, i: U0, _: Equal) -> Self::Remainder { + i + } +} + +// R > D, I == 0: We set R -= D, Q[I] = 1, and return +impl<N, D, Q, R> PrivateDivIf<N, D, Q, R, U0, Greater> for () +where + R: Sub<D>, + Q: SetBit<U0, B1>, +{ + type Quotient = SetBitOut<Q, U0, B1>; + type Remainder = Diff<R, D>; + + #[inline] + fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, i: U0, _: Greater) -> Self::Quotient { + q.set_bit::<Internal>(i, B1) + } + + #[inline] + fn private_div_if_remainder( + self, + _: N, + d: D, + _: Q, + r: R, + _: U0, + _: Greater, + ) -> Self::Remainder { + r - d + } +} + +// ----------------------------------------- +// PartialDiv +use crate::{PartialDiv, Quot}; +impl<Ur: Unsigned, Br: Bit> PartialDiv<UInt<Ur, Br>> for UTerm { + type Output = UTerm; + #[inline] + fn partial_div(self, _: UInt<Ur, Br>) -> Self::Output { + UTerm + } +} + +// M / N +impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit> PartialDiv<UInt<Ur, Br>> for UInt<Ul, Bl> +where + UInt<Ul, Bl>: Div<UInt<Ur, Br>> + Rem<UInt<Ur, Br>, Output = U0>, +{ + type Output = Quot<UInt<Ul, Bl>, UInt<Ur, Br>>; + #[inline] + fn partial_div(self, rhs: UInt<Ur, Br>) -> Self::Output { + self / rhs + } +} + +// ----------------------------------------- +// PrivateMin +use crate::private::{PrivateMin, PrivateMinOut}; + +impl<U, B, Ur> PrivateMin<Ur, Equal> for UInt<U, B> +where + Ur: Unsigned, + U: Unsigned, + B: Bit, +{ + type Output = UInt<U, B>; + #[inline] + fn private_min(self, _: Ur) -> Self::Output { + self + } +} + +impl<U, B, Ur> PrivateMin<Ur, Less> for UInt<U, B> +where + Ur: Unsigned, + U: Unsigned, + B: Bit, +{ + type Output = UInt<U, B>; + #[inline] + fn private_min(self, _: Ur) -> Self::Output { + self + } +} + +impl<U, B, Ur> PrivateMin<Ur, Greater> for UInt<U, B> +where + Ur: Unsigned, + U: Unsigned, + B: Bit, +{ + type Output = Ur; + #[inline] + fn private_min(self, rhs: Ur) -> Self::Output { + rhs + } +} + +// ----------------------------------------- +// Min +use crate::Min; + +impl<U> Min<U> for UTerm +where + U: Unsigned, +{ + type Output = UTerm; + #[inline] + fn min(self, _: U) -> Self::Output { + self + } +} + +impl<U, B, Ur> Min<Ur> for UInt<U, B> +where + U: Unsigned, + B: Bit, + Ur: Unsigned, + UInt<U, B>: Cmp<Ur> + PrivateMin<Ur, Compare<UInt<U, B>, Ur>>, +{ + type Output = PrivateMinOut<UInt<U, B>, Ur, Compare<UInt<U, B>, Ur>>; + #[inline] + fn min(self, rhs: Ur) -> Self::Output { + self.private_min(rhs) + } +} + +// ----------------------------------------- +// PrivateMax +use crate::private::{PrivateMax, PrivateMaxOut}; + +impl<U, B, Ur> PrivateMax<Ur, Equal> for UInt<U, B> +where + Ur: Unsigned, + U: Unsigned, + B: Bit, +{ + type Output = UInt<U, B>; + #[inline] + fn private_max(self, _: Ur) -> Self::Output { + self + } +} + +impl<U, B, Ur> PrivateMax<Ur, Less> for UInt<U, B> +where + Ur: Unsigned, + U: Unsigned, + B: Bit, +{ + type Output = Ur; + #[inline] + fn private_max(self, rhs: Ur) -> Self::Output { + rhs + } +} + +impl<U, B, Ur> PrivateMax<Ur, Greater> for UInt<U, B> +where + Ur: Unsigned, + U: Unsigned, + B: Bit, +{ + type Output = UInt<U, B>; + #[inline] + fn private_max(self, _: Ur) -> Self::Output { + self + } +} + +// ----------------------------------------- +// Max +use crate::Max; + +impl<U> Max<U> for UTerm +where + U: Unsigned, +{ + type Output = U; + #[inline] + fn max(self, rhs: U) -> Self::Output { + rhs + } +} + +impl<U, B, Ur> Max<Ur> for UInt<U, B> +where + U: Unsigned, + B: Bit, + Ur: Unsigned, + UInt<U, B>: Cmp<Ur> + PrivateMax<Ur, Compare<UInt<U, B>, Ur>>, +{ + type Output = PrivateMaxOut<UInt<U, B>, Ur, Compare<UInt<U, B>, Ur>>; + #[inline] + fn max(self, rhs: Ur) -> Self::Output { + self.private_max(rhs) + } +} + +// ----------------------------------------- +// SquareRoot + +impl<N> SquareRoot for N +where + N: PrivateSquareRoot, +{ + type Output = <Self as PrivateSquareRoot>::Output; +} + +// sqrt(0) = 0. +impl PrivateSquareRoot for UTerm { + type Output = UTerm; +} + +// sqrt(1) = 1. +impl PrivateSquareRoot for UInt<UTerm, B1> { + type Output = UInt<UTerm, B1>; +} + +// General case of sqrt(Self) where Self >= 2. If a and b are +// bit-valued and Self = 4*u + 2*a + b, then the integer-valued +// (fractional part truncated) square root of Self is either 2*sqrt(u) +// or 2*sqrt(u)+1. Guess and check by comparing (2*sqrt(u)+1)^2 +// against Self. Since the `typenum` result of that comparison is a +// bit, directly add that bit to 2*sqrt(u). +// +// Use `Sum<Double<Sqrt<U>>, GrEq<...>>` instead of `UInt<Sqrt<U>, +// GrEq<...>>` because `Sqrt<U>` can turn out to be `UTerm` and +// `GrEq<...>` can turn out to be `B0`, which would not be a valid +// UInt as leading zeros are disallowed. +impl<U, Ba, Bb> PrivateSquareRoot for UInt<UInt<U, Ba>, Bb> +where + U: Unsigned, + Ba: Bit, + Bb: Bit, + U: SquareRoot, + Sqrt<U>: Shl<B1>, + Double<Sqrt<U>>: Add<B1>, + Add1<Double<Sqrt<U>>>: Mul, + Self: IsGreaterOrEqual<Square<Add1<Double<Sqrt<U>>>>>, + Double<Sqrt<U>>: Add<GrEq<Self, Square<Add1<Double<Sqrt<U>>>>>>, +{ + type Output = Sum<Double<Sqrt<U>>, GrEq<Self, Square<Add1<Double<Sqrt<U>>>>>>; +} + +#[test] +fn sqrt_test() { + use crate::consts::*; + + assert_eq!(0, <Sqrt<U0>>::to_u32()); + + assert_eq!(1, <Sqrt<U1>>::to_u32()); + assert_eq!(1, <Sqrt<U2>>::to_u32()); + assert_eq!(1, <Sqrt<U3>>::to_u32()); + + assert_eq!(2, <Sqrt<U4>>::to_u32()); + assert_eq!(2, <Sqrt<U5>>::to_u32()); + assert_eq!(2, <Sqrt<U6>>::to_u32()); + assert_eq!(2, <Sqrt<U7>>::to_u32()); + assert_eq!(2, <Sqrt<U8>>::to_u32()); + + assert_eq!(3, <Sqrt<U9>>::to_u32()); + assert_eq!(3, <Sqrt<U10>>::to_u32()); + assert_eq!(3, <Sqrt<U11>>::to_u32()); + assert_eq!(3, <Sqrt<U12>>::to_u32()); + assert_eq!(3, <Sqrt<U13>>::to_u32()); + assert_eq!(3, <Sqrt<U14>>::to_u32()); + assert_eq!(3, <Sqrt<U15>>::to_u32()); + + assert_eq!(4, <Sqrt<U16>>::to_u32()); + assert_eq!(4, <Sqrt<U17>>::to_u32()); + assert_eq!(4, <Sqrt<U18>>::to_u32()); + assert_eq!(4, <Sqrt<U19>>::to_u32()); + assert_eq!(4, <Sqrt<U20>>::to_u32()); + assert_eq!(4, <Sqrt<U21>>::to_u32()); + assert_eq!(4, <Sqrt<U22>>::to_u32()); + assert_eq!(4, <Sqrt<U23>>::to_u32()); + assert_eq!(4, <Sqrt<U24>>::to_u32()); + + assert_eq!(5, <Sqrt<U25>>::to_u32()); + assert_eq!(5, <Sqrt<U26>>::to_u32()); + // ... +} + +// ----------------------------------------- +// Logarithm2 + +impl<N> Logarithm2 for N +where + N: PrivateLogarithm2, +{ + type Output = <Self as PrivateLogarithm2>::Output; +} + +// log2(1) = 0. +impl PrivateLogarithm2 for UInt<UTerm, B1> { + type Output = U0; +} + +// General case of log2(Self) where Self >= 2. +impl<U, B> PrivateLogarithm2 for UInt<U, B> +where + U: Unsigned + Logarithm2, + B: Bit, + Log2<U>: Add<B1>, +{ + type Output = Add1<Log2<U>>; +} + +// ----------------------------------------- +// ToInt + +impl ToInt<i8> for UTerm { + #[inline] + fn to_int() -> i8 { + Self::I8 + } + const INT: i8 = Self::I8; +} + +impl ToInt<i16> for UTerm { + #[inline] + fn to_int() -> i16 { + Self::I16 + } + const INT: i16 = Self::I16; +} + +impl ToInt<i32> for UTerm { + #[inline] + fn to_int() -> i32 { + Self::I32 + } + const INT: i32 = Self::I32; +} + +impl ToInt<i64> for UTerm { + #[inline] + fn to_int() -> i64 { + Self::I64 + } + const INT: i64 = Self::I64; +} + +impl ToInt<u8> for UTerm { + #[inline] + fn to_int() -> u8 { + Self::U8 + } + const INT: u8 = Self::U8; +} + +impl ToInt<u16> for UTerm { + #[inline] + fn to_int() -> u16 { + Self::U16 + } + const INT: u16 = Self::U16; +} + +impl ToInt<u32> for UTerm { + #[inline] + fn to_int() -> u32 { + Self::U32 + } + const INT: u32 = Self::U32; +} + +impl ToInt<u64> for UTerm { + #[inline] + fn to_int() -> u64 { + Self::U64 + } + const INT: u64 = Self::U64; +} + +impl ToInt<usize> for UTerm { + #[inline] + fn to_int() -> usize { + Self::USIZE + } + const INT: usize = Self::USIZE; +} + +impl<U, B> ToInt<i8> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> i8 { + Self::I8 + } + const INT: i8 = Self::I8; +} + +impl<U, B> ToInt<i16> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> i16 { + Self::I16 + } + const INT: i16 = Self::I16; +} + +impl<U, B> ToInt<i32> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> i32 { + Self::I32 + } + const INT: i32 = Self::I32; +} + +impl<U, B> ToInt<i64> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> i64 { + Self::I64 + } + const INT: i64 = Self::I64; +} + +impl<U, B> ToInt<u8> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> u8 { + Self::U8 + } + const INT: u8 = Self::U8; +} + +impl<U, B> ToInt<u16> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> u16 { + Self::U16 + } + const INT: u16 = Self::U16; +} + +impl<U, B> ToInt<u32> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> u32 { + Self::U32 + } + const INT: u32 = Self::U32; +} + +impl<U, B> ToInt<u64> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> u64 { + Self::U64 + } + const INT: u64 = Self::U64; +} + +impl<U, B> ToInt<usize> for UInt<U, B> +where + U: Unsigned, + B: Bit, +{ + #[inline] + fn to_int() -> usize { + Self::USIZE + } + const INT: usize = Self::USIZE; +} + +#[cfg(test)] +mod tests { + use crate::consts::*; + use crate::{Log2, ToInt, Unsigned}; + + #[test] + fn log2_test() { + assert_eq!(0, <Log2<U1>>::to_u32()); + + assert_eq!(1, <Log2<U2>>::to_u32()); + assert_eq!(1, <Log2<U3>>::to_u32()); + + assert_eq!(2, <Log2<U4>>::to_u32()); + assert_eq!(2, <Log2<U5>>::to_u32()); + assert_eq!(2, <Log2<U6>>::to_u32()); + assert_eq!(2, <Log2<U7>>::to_u32()); + + assert_eq!(3, <Log2<U8>>::to_u32()); + assert_eq!(3, <Log2<U9>>::to_u32()); + assert_eq!(3, <Log2<U10>>::to_u32()); + assert_eq!(3, <Log2<U11>>::to_u32()); + assert_eq!(3, <Log2<U12>>::to_u32()); + assert_eq!(3, <Log2<U13>>::to_u32()); + assert_eq!(3, <Log2<U14>>::to_u32()); + assert_eq!(3, <Log2<U15>>::to_u32()); + + assert_eq!(4, <Log2<U16>>::to_u32()); + assert_eq!(4, <Log2<U17>>::to_u32()); + assert_eq!(4, <Log2<U18>>::to_u32()); + assert_eq!(4, <Log2<U19>>::to_u32()); + assert_eq!(4, <Log2<U20>>::to_u32()); + assert_eq!(4, <Log2<U21>>::to_u32()); + assert_eq!(4, <Log2<U22>>::to_u32()); + assert_eq!(4, <Log2<U23>>::to_u32()); + assert_eq!(4, <Log2<U24>>::to_u32()); + assert_eq!(4, <Log2<U25>>::to_u32()); + assert_eq!(4, <Log2<U26>>::to_u32()); + assert_eq!(4, <Log2<U27>>::to_u32()); + assert_eq!(4, <Log2<U28>>::to_u32()); + assert_eq!(4, <Log2<U29>>::to_u32()); + assert_eq!(4, <Log2<U30>>::to_u32()); + assert_eq!(4, <Log2<U31>>::to_u32()); + + assert_eq!(5, <Log2<U32>>::to_u32()); + assert_eq!(5, <Log2<U33>>::to_u32()); + + // ... + } + + #[test] + fn uint_toint_test() { + // i8 + assert_eq!(0_i8, U0::to_int()); + assert_eq!(1_i8, U1::to_int()); + assert_eq!(2_i8, U2::to_int()); + assert_eq!(3_i8, U3::to_int()); + assert_eq!(4_i8, U4::to_int()); + assert_eq!(0_i8, U0::INT); + assert_eq!(1_i8, U1::INT); + assert_eq!(2_i8, U2::INT); + assert_eq!(3_i8, U3::INT); + assert_eq!(4_i8, U4::INT); + + // i16 + assert_eq!(0_i16, U0::to_int()); + assert_eq!(1_i16, U1::to_int()); + assert_eq!(2_i16, U2::to_int()); + assert_eq!(3_i16, U3::to_int()); + assert_eq!(4_i16, U4::to_int()); + assert_eq!(0_i16, U0::INT); + assert_eq!(1_i16, U1::INT); + assert_eq!(2_i16, U2::INT); + assert_eq!(3_i16, U3::INT); + assert_eq!(4_i16, U4::INT); + + // i32 + assert_eq!(0_i32, U0::to_int()); + assert_eq!(1_i32, U1::to_int()); + assert_eq!(2_i32, U2::to_int()); + assert_eq!(3_i32, U3::to_int()); + assert_eq!(4_i32, U4::to_int()); + assert_eq!(0_i32, U0::INT); + assert_eq!(1_i32, U1::INT); + assert_eq!(2_i32, U2::INT); + assert_eq!(3_i32, U3::INT); + assert_eq!(4_i32, U4::INT); + + // i64 + assert_eq!(0_i64, U0::to_int()); + assert_eq!(1_i64, U1::to_int()); + assert_eq!(2_i64, U2::to_int()); + assert_eq!(3_i64, U3::to_int()); + assert_eq!(4_i64, U4::to_int()); + assert_eq!(0_i64, U0::INT); + assert_eq!(1_i64, U1::INT); + assert_eq!(2_i64, U2::INT); + assert_eq!(3_i64, U3::INT); + assert_eq!(4_i64, U4::INT); + + // u8 + assert_eq!(0_u8, U0::to_int()); + assert_eq!(1_u8, U1::to_int()); + assert_eq!(2_u8, U2::to_int()); + assert_eq!(3_u8, U3::to_int()); + assert_eq!(4_u8, U4::to_int()); + assert_eq!(0_u8, U0::INT); + assert_eq!(1_u8, U1::INT); + assert_eq!(2_u8, U2::INT); + assert_eq!(3_u8, U3::INT); + assert_eq!(4_u8, U4::INT); + + // u16 + assert_eq!(0_u16, U0::to_int()); + assert_eq!(1_u16, U1::to_int()); + assert_eq!(2_u16, U2::to_int()); + assert_eq!(3_u16, U3::to_int()); + assert_eq!(4_u16, U4::to_int()); + assert_eq!(0_u16, U0::INT); + assert_eq!(1_u16, U1::INT); + assert_eq!(2_u16, U2::INT); + assert_eq!(3_u16, U3::INT); + assert_eq!(4_u16, U4::INT); + + // u32 + assert_eq!(0_u32, U0::to_int()); + assert_eq!(1_u32, U1::to_int()); + assert_eq!(2_u32, U2::to_int()); + assert_eq!(3_u32, U3::to_int()); + assert_eq!(4_u32, U4::to_int()); + assert_eq!(0_u32, U0::INT); + assert_eq!(1_u32, U1::INT); + assert_eq!(2_u32, U2::INT); + assert_eq!(3_u32, U3::INT); + assert_eq!(4_u32, U4::INT); + + // u64 + assert_eq!(0_u64, U0::to_int()); + assert_eq!(1_u64, U1::to_int()); + assert_eq!(2_u64, U2::to_int()); + assert_eq!(3_u64, U3::to_int()); + assert_eq!(4_u64, U4::to_int()); + assert_eq!(0_u64, U0::INT); + assert_eq!(1_u64, U1::INT); + assert_eq!(2_u64, U2::INT); + assert_eq!(3_u64, U3::INT); + assert_eq!(4_u64, U4::INT); + + // usize + assert_eq!(0_usize, U0::to_int()); + assert_eq!(1_usize, U1::to_int()); + assert_eq!(2_usize, U2::to_int()); + assert_eq!(3_usize, U3::to_int()); + assert_eq!(4_usize, U4::to_int()); + assert_eq!(0_usize, U0::INT); + assert_eq!(1_usize, U1::INT); + assert_eq!(2_usize, U2::INT); + assert_eq!(3_usize, U3::INT); + assert_eq!(4_usize, U4::INT); + } +} diff --git a/third_party/rust/typenum/tests/test.rs b/third_party/rust/typenum/tests/test.rs new file mode 100644 index 0000000000..fc9e1ffab5 --- /dev/null +++ b/third_party/rust/typenum/tests/test.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +include!(concat!(env!("OUT_DIR"), "/tests.rs")); |