From f4f5d1a71040f72202b79c39c47a9c3aece7bf08 Mon Sep 17 00:00:00 2001 From: Jack Bernard Date: Mon, 25 Dec 2023 09:51:27 -0600 Subject: [PATCH] initial commit --- .gitignore | 2 + Cargo.toml | 23 + LICENSE-APACHE | 176 + LICENSE-MIT | 23 + README.md | 23 + src/aint.rs | 10213 ++++++++++++++++++++++++++++++++++++++++++++ src/bit_concat.rs | 26 + src/bit_split.rs | 24 + src/convs.rs | 2255 ++++++++++ src/int.rs | 214 + src/lib.rs | 150 + src/macros.rs | 434 ++ src/misc.rs | 44 + src/non_prim.rs | 365 ++ src/num.rs | 6355 +++++++++++++++++++++++++++ src/ops.rs | 412 ++ src/prim.rs | 273 ++ src/saturating.rs | 1040 +++++ src/sealed.rs | 21 + src/serde.rs | 301 ++ src/shifts.rs | 2726 ++++++++++++ src/test.rs | 538 +++ src/tybit.rs | 194 + src/typedefs.rs | 520 +++ src/width.rs | 388 ++ src/wrapping.rs | 930 ++++ 26 files changed, 27670 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 src/aint.rs create mode 100644 src/bit_concat.rs create mode 100644 src/bit_split.rs create mode 100644 src/convs.rs create mode 100644 src/int.rs create mode 100644 src/lib.rs create mode 100644 src/macros.rs create mode 100644 src/misc.rs create mode 100644 src/non_prim.rs create mode 100644 src/num.rs create mode 100644 src/ops.rs create mode 100644 src/prim.rs create mode 100644 src/saturating.rs create mode 100644 src/sealed.rs create mode 100644 src/serde.rs create mode 100644 src/shifts.rs create mode 100644 src/test.rs create mode 100644 src/tybit.rs create mode 100644 src/typedefs.rs create mode 100644 src/width.rs create mode 100644 src/wrapping.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d0cff87 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "aint" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +authors = ["Jack Bernard "] +repository = "https://github.com/Vociferix/aint" +description = "Arbitrary width integers between 1 and 128" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0", optional = true } +num-traits = { version = "0.2", optional = true } +num-integer = { version = "0.1", optional = true } + +[dev-dependencies] +paste = "1.0" + +[features] +default = [] +serde = ["dep:serde"] +num = ["dep:num-traits", "dep:num-integer"] diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..7895bcd --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,176 @@ + 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 diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +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/README.md b/README.md new file mode 100644 index 0000000..df308e2 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Aint + +Aint is a crate implementing integers of non-standard bit widths between +1 and 127. These integer types are represented by the next largest built-in +Rust integer, but are bounded to the range and behaviors of the advertised +bit width. That is, `T::MIN` and `T::MAX`, are what would be expected for +the integer `T` with `N` bits, and similarly, wrapping, saturating, and +overflow behaviors match what would be expected for a hypothetical built-in +integer `T` with `N` bits. + +### Example +``` +# use aint::*; +fn add(a: i13, b: i13) -> i13 { +a + b +} + +let x = i13!(100); +let y = add(x, i13!(-42)); +assert_eq!(y, i13!(58)); +``` + +See [the documentation](https://docs.rs/aint/latest/aint/) for details. diff --git a/src/aint.rs b/src/aint.rs new file mode 100644 index 0000000..d463e57 --- /dev/null +++ b/src/aint.rs @@ -0,0 +1,10213 @@ +use crate::sealed::Sealed; + +/// An integer with a given representation, `R`, and bit width, `WIDTH`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct Aint(pub(crate) R); + +fn make_parse_int_err() -> core::num::ParseIntError { + let Err(e) = u8::from_str_radix("256", 10) else { + unreachable!() + }; + e +} + +impl Aint { + pub(crate) fn _min() -> Self { + if R::SIGNED { + Self(!R::ZERO << (WIDTH - 1)) + } else { + Self(R::ZERO) + } + } + + pub(crate) fn _max() -> Self { + if R::SIGNED { + Self(!Self::_min().0) + } else { + Self(!(!R::ZERO << WIDTH)) + } + } + + pub(crate) fn _mask() -> R { + !(!R::ZERO << WIDTH) + } + + pub(crate) fn _sign_bit() -> R { + if R::SIGNED { + R::ONE << (WIDTH - 1) + } else { + R::ZERO + } + } + + pub(crate) fn _new(repr: R) -> Option { + if repr <= Self::_max().0 && repr >= Self::_min().0 { + Some(Self(repr)) + } else { + None + } + } + + pub(crate) fn _new_wrapping(repr: R) -> Self { + if (repr & Self::_sign_bit()) == R::ZERO { + Self(repr & Self::_max().0) + } else { + Self(repr | !Self::_max().0) + } + } + + pub(crate) fn _new_saturating(repr: R) -> Self { + if repr >= Self::_max().0 { + Self::_max() + } else if repr <= Self::_min().0 { + Self::_min() + } else { + Self(repr) + } + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 0 && WIDTH < u8::BITS { + () + } else { + panic!("Invalid Aint width with repr type u8") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(0) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(u8::MAX >> (u8::BITS - WIDTH)) + }; + + pub(crate) const MASK: u8 = { + let _val = Self::ASSERT; + u8::MAX >> (u8::BITS - WIDTH) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: u8) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: u8) -> Option { + if repr <= Self::MAX.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: u8) -> Self { + Self(repr & Self::MAX.0) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: u8) -> Self { + if repr <= Self::MAX.0 { + Self(repr) + } else { + Self::MAX + } + } + + const fn new_overflowing_impl((repr, over): (u8, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MASK), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: u8) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> u8 { + self.0 + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() - (u8::BITS - Self::BITS) + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() - (u8::BITS - Self::BITS) + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 << (u8::BITS - Self::BITS)).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + self.0.trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | (self.0 >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (u8::BITS - Self::BITS)) + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0 - rhs.0) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + Self(self.0 / rhs.0) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0 & Self::MASK) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Self { + Self(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(u8::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 8 && WIDTH < 16 { + () + } else { + panic!("Invalid width for Aint with repr type of u16"); + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(0) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(u16::MAX >> (u16::BITS - WIDTH)) + }; + + pub(crate) const MASK: u16 = { + let _val = Self::ASSERT; + u16::MAX >> (u16::BITS - WIDTH) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: u16) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: u16) -> Option { + if repr <= Self::MAX.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: u16) -> Self { + Self(repr & Self::MAX.0) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: u16) -> Self { + if repr <= Self::MAX.0 { + Self(repr) + } else { + Self::MAX + } + } + + const fn new_overflowing_impl((repr, over): (u16, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MASK), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: u16) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> u16 { + self.0 + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() - (u16::BITS - Self::BITS) + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() - (u16::BITS - Self::BITS) + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 << (u16::BITS - Self::BITS)).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + self.0.trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | (self.0 >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (u16::BITS - Self::BITS)) + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0 - rhs.0) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + Self(self.0 / rhs.0) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0 & Self::MASK) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Self { + Self(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(u16::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 16 && WIDTH < 32 { + () + } else { + panic!("Invalid width for Aint with repr type of u32") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(0) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(u32::MAX >> (u32::BITS - WIDTH)) + }; + + pub(crate) const MASK: u32 = { + let _val = Self::ASSERT; + u32::MAX >> (u32::BITS - WIDTH) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: u32) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: u32) -> Option { + if repr <= Self::MAX.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: u32) -> Self { + Self(repr & Self::MAX.0) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: u32) -> Self { + if repr <= Self::MAX.0 { + Self(repr) + } else { + Self::MAX + } + } + + const fn new_overflowing_impl((repr, over): (u32, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MASK), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: u32) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> u32 { + self.0 + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() - (u32::BITS - Self::BITS) + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() - (u32::BITS - Self::BITS) + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 << (u32::BITS - Self::BITS)).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + self.0.trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | (self.0 >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (u32::BITS - Self::BITS)) + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0 - rhs.0) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + Self(self.0 / rhs.0) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0 & Self::MASK) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Self { + Self(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(u32::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 8) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 3]) -> Self { + Self(u32::from_be_bytes([0, bytes[0], bytes[1], bytes[2]])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 3]) -> Self { + Self(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 3]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 3] { + let tmp = self.0.to_be_bytes(); + [tmp[1], tmp[2], tmp[3]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 3] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 3] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 32 && WIDTH < 64 { + () + } else { + panic!("Invalid width for Aint with repr type of u64") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(0) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(u64::MAX >> (u64::BITS - WIDTH)) + }; + + pub(crate) const MASK: u64 = { + let _val = Self::ASSERT; + u64::MAX >> (u64::BITS - WIDTH) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: u64) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: u64) -> Option { + if repr <= Self::MAX.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: u64) -> Self { + Self(repr & Self::MAX.0) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: u64) -> Self { + if repr <= Self::MAX.0 { + Self(repr) + } else { + Self::MAX + } + } + + const fn new_overflowing_impl((repr, over): (u64, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MASK), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: u64) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> u64 { + self.0 + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() - (u64::BITS - Self::BITS) + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() - (u64::BITS - Self::BITS) + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 << (u64::BITS - Self::BITS)).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + self.0.trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | (self.0 >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (u64::BITS - Self::BITS)) + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0 - rhs.0) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + Self(self.0 / rhs.0) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0 & Self::MASK) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Self { + Self(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(u64::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 24) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 5]) -> Self { + Self(u64::from_be_bytes([ + 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 5]) -> Self { + Self(u64::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 5]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 5] { + let tmp = self.0.to_be_bytes(); + [tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 5] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 5] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 16) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 6]) -> Self { + Self(u64::from_be_bytes([ + 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 6]) -> Self { + Self(u64::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 6]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 6] { + let tmp = self.0.to_be_bytes(); + [tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 6] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 6] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 8) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 7]) -> Self { + Self(u64::from_be_bytes([ + 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 7]) -> Self { + Self(u64::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 7]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 7] { + let tmp = self.0.to_be_bytes(); + [tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 7] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 7] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 64 && WIDTH < 128 { + () + } else { + panic!("Invalid width for Aint with repr type of u128") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(0) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(u128::MAX >> (u128::BITS - WIDTH)) + }; + + pub(crate) const MASK: u128 = { + let _val = Self::ASSERT; + u128::MAX >> (u128::BITS - WIDTH) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: u128) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: u128) -> Option { + if repr <= Self::MAX.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: u128) -> Self { + Self(repr & Self::MAX.0) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: u128) -> Self { + if repr <= Self::MAX.0 { + Self(repr) + } else { + Self::MAX + } + } + + const fn new_overflowing_impl((repr, over): (u128, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MASK), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: u128) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> u128 { + self.0 + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() - (u128::BITS - Self::BITS) + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() - (u128::BITS - Self::BITS) + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 << (u128::BITS - Self::BITS)).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + self.0.trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | (self.0 >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (u128::BITS - Self::BITS)) + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0 - rhs.0) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + Self(self.0 / rhs.0) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0 & Self::MASK) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Self { + Self(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(u128::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 56) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 9]) -> Self { + Self(u128::from_be_bytes([ + 0, 0, 0, 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], + bytes[6], bytes[7], bytes[8], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 9]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], 0, 0, 0, 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 9]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 9] { + let tmp = self.0.to_be_bytes(); + [ + tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 9] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 9] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 48) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 10]) -> Self { + Self(u128::from_be_bytes([ + 0, 0, 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 10]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], 0, 0, 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 10]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 10] { + let tmp = self.0.to_be_bytes(); + [ + tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 10] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 10] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 40) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 11]) -> Self { + Self(u128::from_be_bytes([ + 0, 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], bytes[10], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 11]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], 0, 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 11]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 11] { + let tmp = self.0.to_be_bytes(); + [ + tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], + tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 11] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 11] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 32) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 12]) -> Self { + Self(u128::from_be_bytes([ + 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 12]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 12]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 12] { + let tmp = self.0.to_be_bytes(); + [ + tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], + tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 12] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 12] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 24) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 13]) -> Self { + Self(u128::from_be_bytes([ + 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 13]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 13]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 13] { + let tmp = self.0.to_be_bytes(); + [ + tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], + tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 13] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], tmp[12], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 13] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 16) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 14]) -> Self { + Self(u128::from_be_bytes([ + 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 14]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 14]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 14] { + let tmp = self.0.to_be_bytes(); + [ + tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], + tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 14] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], tmp[12], tmp[13], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 14] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self(self.0.swap_bytes() >> 8) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 15]) -> Self { + Self(u128::from_be_bytes([ + 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 15]) -> Self { + Self(u128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 15]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 15] { + let tmp = self.0.to_be_bytes(); + [ + tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], + tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 15] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 15] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 0 && WIDTH < 8 { + () + } else { + panic!("Invalid width for Aint with repr type of i8") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(!0 << (Self::BITS - 1)) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(!Self::MIN.0) + }; + + pub(crate) const MASK: i8 = { + let _val = Self::ASSERT; + (Self::MAX.0 << 1) | 1 + }; + + const SIGN_BIT: i8 = { + let _val = Self::ASSERT; + 1 << (Self::BITS - 1) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: i8) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: i8) -> Option { + if repr <= Self::MAX.0 && repr >= Self::MIN.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: i8) -> Self { + if (repr & Self::SIGN_BIT) == 0 { + Self(repr & Self::MAX.0) + } else { + Self(repr | !Self::MAX.0) + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: i8) -> Self { + if repr >= Self::MAX.0 { + Self::MAX + } else if repr <= Self::MIN.0 { + Self::MIN + } else { + Self(repr) + } + } + + const fn new_overflowing_impl((repr, over): (i8, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MAX.0), true) + } else if repr < Self::MIN.0 { + (Self(repr | !Self::MAX.0), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: i8) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> i8 { + self.0 + } + + /// Returns `true` if this integer is less than zero. + pub const fn is_negative(self) -> bool { + (self.0 & Self::SIGN_BIT) != 0 + } + + /// Returns `true` if this integer is greater than zero. + pub const fn is_positive(self) -> bool { + self.0 != 0 && (self.0 & Self::SIGN_BIT) == 0 + } + + /// Returns the sign of the integer. + /// + /// * If `self < 0`, returns `-1` + /// * If `self > 0`, returns `1` + /// * If `self == 0`, returns `0` + pub const fn signum(self) -> Self { + if self.0 == 0 { + Self(0) + } else if self.0 > 0 { + Self(1) + } else { + Self(-1) + } + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + (self.0 & Self::MASK).count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + (self.0 | !Self::MASK).count_zeros() + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + if self.is_negative() { + 0 + } else { + self.0.leading_zeros() - (i8::BITS - Self::BITS) + } + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 | !Self::MASK).leading_ones() - (i8::BITS - Self::BITS) + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + (self.0 & Self::MASK).trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | ((self.0 & Self::MASK) >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping(((self.0 & Self::MASK) >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (i8::BITS - Self::BITS)) + } + + /// Calculates the negative of this integer. + /// + /// This method works as a `const` capable alternative to `-self`. + pub const fn neg(self) -> Self { + debug_assert!(self.0 != Self::MIN.0, "attempt to negate with overflow"); + self.wrapping_neg() + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + let val = self.0 - rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to subtract with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + let val = self.0 / rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self(val) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + let val = self.0 % rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to calculate modulus with overflow" + ); + Self(val) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Wrapping (modular) aboslute value. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Calculates `self.abs()`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_abs(self) -> (Self, bool) { + if self.is_negative() { + self.overflowing_neg() + } else { + (self, false) + } + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute value of this integer. + pub const fn abs(self) -> Self { + debug_assert!( + self.0 != Self::MIN.0, + "attempt to calculate absolute value with overflow" + ); + self.wrapping_abs() + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Aint { + Aint(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(i8::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 8 && WIDTH < 16 { + () + } else { + panic!("Invalid width for Aint with repr type of i16") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(!0 << (Self::BITS - 1)) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(!Self::MIN.0) + }; + + pub(crate) const MASK: i16 = { + let _val = Self::ASSERT; + (Self::MAX.0 << 1) | 1 + }; + + const SIGN_BIT: i16 = { + let _val = Self::ASSERT; + 1 << (Self::BITS - 1) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: i16) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: i16) -> Option { + if repr <= Self::MAX.0 && repr >= Self::MIN.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: i16) -> Self { + if (repr & Self::SIGN_BIT) == 0 { + Self(repr & Self::MAX.0) + } else { + Self(repr | !Self::MAX.0) + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: i16) -> Self { + if repr >= Self::MAX.0 { + Self::MAX + } else if repr <= Self::MIN.0 { + Self::MIN + } else { + Self(repr) + } + } + + const fn new_overflowing_impl((repr, over): (i16, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MAX.0), true) + } else if repr < Self::MIN.0 { + (Self(repr | !Self::MAX.0), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: i16) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> i16 { + self.0 + } + + /// Returns `true` if this integer is less than zero. + pub const fn is_negative(self) -> bool { + (self.0 & Self::SIGN_BIT) != 0 + } + + /// Returns `true` if this integer is greater than zero. + pub const fn is_positive(self) -> bool { + self.0 != 0 && (self.0 & Self::SIGN_BIT) == 0 + } + + /// Returns the sign of the integer. + /// + /// * If `self < 0`, returns `-1` + /// * If `self > 0`, returns `1` + /// * If `self == 0`, returns `0` + pub const fn signum(self) -> Self { + if self.0 == 0 { + Self(0) + } else if self.0 > 0 { + Self(1) + } else { + Self(-1) + } + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + (self.0 & Self::MASK).count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + (self.0 | !Self::MASK).count_zeros() + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + if self.is_negative() { + 0 + } else { + self.0.leading_zeros() - (i16::BITS - Self::BITS) + } + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 | !Self::MASK).leading_ones() - (i16::BITS - Self::BITS) + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + (self.0 & Self::MASK).trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | ((self.0 & Self::MASK) >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping(((self.0 & Self::MASK) >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (i16::BITS - Self::BITS)) + } + + /// Calculates the negative of this integer. + /// + /// This method works as a `const` capable alternative to `-self`. + pub const fn neg(self) -> Self { + debug_assert!(self.0 != Self::MIN.0, "attempt to negate with overflow"); + self.wrapping_neg() + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + let val = self.0 - rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to subtract with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + let val = self.0 / rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self(val) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + let val = self.0 % rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to calculate modulus with overflow" + ); + Self(val) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Wrapping (modular) aboslute value. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Calculates `self.abs()`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_abs(self) -> (Self, bool) { + if self.is_negative() { + self.overflowing_neg() + } else { + (self, false) + } + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute value of this integer. + pub const fn abs(self) -> Self { + debug_assert!( + self.0 != Self::MIN.0, + "attempt to calculate absolute value with overflow" + ); + self.wrapping_abs() + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Aint { + Aint(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(i16::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 16 && WIDTH < 32 { + () + } else { + panic!("Invalid width for Aint with repr type of i32") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(!0 << (Self::BITS - 1)) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(!Self::MIN.0) + }; + + pub(crate) const MASK: i32 = { + let _val = Self::ASSERT; + (Self::MAX.0 << 1) | 1 + }; + + const SIGN_BIT: i32 = { + let _val = Self::ASSERT; + 1 << (Self::BITS - 1) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: i32) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: i32) -> Option { + if repr <= Self::MAX.0 && repr >= Self::MIN.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: i32) -> Self { + if (repr & Self::SIGN_BIT) == 0 { + Self(repr & Self::MAX.0) + } else { + Self(repr | !Self::MAX.0) + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: i32) -> Self { + if repr >= Self::MAX.0 { + Self::MAX + } else if repr <= Self::MIN.0 { + Self::MIN + } else { + Self(repr) + } + } + + const fn new_overflowing_impl((repr, over): (i32, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MAX.0), true) + } else if repr < Self::MIN.0 { + (Self(repr | !Self::MAX.0), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: i32) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> i32 { + self.0 + } + + /// Returns `true` if this integer is less than zero. + pub const fn is_negative(self) -> bool { + (self.0 & Self::SIGN_BIT) != 0 + } + + /// Returns `true` if this integer is greater than zero. + pub const fn is_positive(self) -> bool { + self.0 != 0 && (self.0 & Self::SIGN_BIT) == 0 + } + + /// Returns the sign of the integer. + /// + /// * If `self < 0`, returns `-1` + /// * If `self > 0`, returns `1` + /// * If `self == 0`, returns `0` + pub const fn signum(self) -> Self { + if self.0 == 0 { + Self(0) + } else if self.0 > 0 { + Self(1) + } else { + Self(-1) + } + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + (self.0 & Self::MASK).count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + (self.0 | !Self::MASK).count_zeros() + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + if self.is_negative() { + 0 + } else { + self.0.leading_zeros() - (i32::BITS - Self::BITS) + } + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 | !Self::MASK).leading_ones() - (i32::BITS - Self::BITS) + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + (self.0 & Self::MASK).trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | ((self.0 & Self::MASK) >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping(((self.0 & Self::MASK) >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (i32::BITS - Self::BITS)) + } + + /// Calculates the negative of this integer. + /// + /// This method works as a `const` capable alternative to `-self`. + pub const fn neg(self) -> Self { + debug_assert!(self.0 != Self::MIN.0, "attempt to negate with overflow"); + self.wrapping_neg() + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + let val = self.0 - rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to subtract with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + let val = self.0 / rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self(val) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + let val = self.0 % rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to calculate modulus with overflow" + ); + Self(val) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Wrapping (modular) aboslute value. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Calculates `self.abs()`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_abs(self) -> (Self, bool) { + if self.is_negative() { + self.overflowing_neg() + } else { + (self, false) + } + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute value of this integer. + pub const fn abs(self) -> Self { + debug_assert!( + self.0 != Self::MIN.0, + "attempt to calculate absolute value with overflow" + ); + self.wrapping_abs() + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Aint { + Aint(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(i32::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 8) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 3]) -> Self { + Self(i32::from_be_bytes([0, bytes[0], bytes[1], bytes[2]])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 3]) -> Self { + Self(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 3]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 3] { + let tmp = self.0.to_be_bytes(); + [tmp[1], tmp[2], tmp[3]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 3] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 3] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 32 && WIDTH < 64 { + () + } else { + panic!("Invalid width for Aint with repr type of i64") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(!0 << (Self::BITS - 1)) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(!Self::MIN.0) + }; + + pub(crate) const MASK: i64 = { + let _val = Self::ASSERT; + (Self::MAX.0 << 1) | 1 + }; + + const SIGN_BIT: i64 = { + let _val = Self::ASSERT; + 1 << (Self::BITS - 1) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: i64) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: i64) -> Option { + if repr <= Self::MAX.0 && repr >= Self::MIN.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: i64) -> Self { + if (repr & Self::SIGN_BIT) == 0 { + Self(repr & Self::MAX.0) + } else { + Self(repr | !Self::MAX.0) + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: i64) -> Self { + if repr >= Self::MAX.0 { + Self::MAX + } else if repr <= Self::MIN.0 { + Self::MIN + } else { + Self(repr) + } + } + + const fn new_overflowing_impl((repr, over): (i64, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MAX.0), true) + } else if repr < Self::MIN.0 { + (Self(repr | !Self::MAX.0), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: i64) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> i64 { + self.0 + } + + /// Returns `true` if this integer is less than zero. + pub const fn is_negative(self) -> bool { + (self.0 & Self::SIGN_BIT) != 0 + } + + /// Returns `true` if this integer is greater than zero. + pub const fn is_positive(self) -> bool { + self.0 != 0 && (self.0 & Self::SIGN_BIT) == 0 + } + + /// Returns the sign of the integer. + /// + /// * If `self < 0`, returns `-1` + /// * If `self > 0`, returns `1` + /// * If `self == 0`, returns `0` + pub const fn signum(self) -> Self { + if self.0 == 0 { + Self(0) + } else if self.0 > 0 { + Self(1) + } else { + Self(-1) + } + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + (self.0 & Self::MASK).count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + (self.0 | !Self::MASK).count_zeros() + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + if self.is_negative() { + 0 + } else { + self.0.leading_zeros() - (i64::BITS - Self::BITS) + } + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 | !Self::MASK).leading_ones() - (i64::BITS - Self::BITS) + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + (self.0 & Self::MASK).trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | ((self.0 & Self::MASK) >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping(((self.0 & Self::MASK) >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (i64::BITS - Self::BITS)) + } + + /// Calculates the negative of this integer. + /// + /// This method works as a `const` capable alternative to `-self`. + pub const fn neg(self) -> Self { + debug_assert!(self.0 != Self::MIN.0, "attempt to negate with overflow"); + self.wrapping_neg() + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + let val = self.0 - rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to subtract with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + let val = self.0 / rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self(val) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + let val = self.0 % rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to calculate modulus with overflow" + ); + Self(val) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Wrapping (modular) aboslute value. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Calculates `self.abs()`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_abs(self) -> (Self, bool) { + if self.is_negative() { + self.overflowing_neg() + } else { + (self, false) + } + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute value of this integer. + pub const fn abs(self) -> Self { + debug_assert!( + self.0 != Self::MIN.0, + "attempt to calculate absolute value with overflow" + ); + self.wrapping_abs() + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Aint { + Aint(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(i64::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 24) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 5]) -> Self { + Self(i64::from_be_bytes([ + 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 5]) -> Self { + Self(i64::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 5]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 5] { + let tmp = self.0.to_be_bytes(); + [tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 5] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 5] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 16) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 6]) -> Self { + Self(i64::from_be_bytes([ + 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 6]) -> Self { + Self(i64::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 6]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 6] { + let tmp = self.0.to_be_bytes(); + [tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 6] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 6] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 8) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 7]) -> Self { + Self(i64::from_be_bytes([ + 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 7]) -> Self { + Self(i64::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 7]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 7] { + let tmp = self.0.to_be_bytes(); + [tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 7] { + let tmp = self.0.to_le_bytes(); + [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6]] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 7] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + const ASSERT: () = if WIDTH > 64 && WIDTH < 128 { + () + } else { + panic!("Invalid width for Aint with repr type of i128") + }; + + /// The size of this integer type in bits. + pub const BITS: u32 = { + let _val = Self::ASSERT; + WIDTH + }; + + /// The smallest value that can be represented by this integer type. + pub const MIN: Self = { + let _val = Self::ASSERT; + Self(!0 << (Self::BITS - 1)) + }; + + /// The largest value that can be represented by this integer type. + pub const MAX: Self = { + let _val = Self::ASSERT; + Self(!Self::MIN.0) + }; + + pub(crate) const MASK: i128 = { + let _val = Self::ASSERT; + (Self::MAX.0 << 1) | 1 + }; + + const SIGN_BIT: i128 = { + let _val = Self::ASSERT; + 1 << (Self::BITS - 1) + }; + + /// Creates a new integer value from the underlying representation type, unchecked. + /// + /// # Safety + /// The representation type value must be within the range of valid values of this type. + /// That is, the value must be greater or equal to [`MIN`](Self::MIN) and less or equal to + /// [`MAX`](Self::MAX). + pub const unsafe fn new_unchecked(repr: i128) -> Self { + let _val = Self::ASSERT; + Self(repr) + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is `None` if the representation value is outside the range of valid + /// values of this integer type. + pub const fn new(repr: i128) -> Option { + if repr <= Self::MAX.0 && repr >= Self::MIN.0 { + Some(Self(repr)) + } else { + None + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is wrapped as though the representation value were calculated using + /// wrapping operations, such as [`wrapping_add`](Self::wrapping_add). + pub const fn new_wrapping(repr: i128) -> Self { + if (repr & Self::SIGN_BIT) == 0 { + Self(repr & Self::MAX.0) + } else { + Self(repr | !Self::MAX.0) + } + } + + /// Creates a new integer value from the underlying representation type. + /// + /// The returned value is saturated to the bounds of this integer's value range. If the + /// representation value is greater than [`MAX`](Self::MAX), the returned value will be + /// [`MAX`](Self::MAX). If the representation value is less than [`MIN`](Self::MIN), the + /// returned value will be [`MIN`](Self::MIN). + pub const fn new_saturating(repr: i128) -> Self { + if repr >= Self::MAX.0 { + Self::MAX + } else if repr <= Self::MIN.0 { + Self::MIN + } else { + Self(repr) + } + } + + const fn new_overflowing_impl((repr, over): (i128, bool)) -> (Self, bool) { + if repr > Self::MAX.0 { + (Self(repr & Self::MAX.0), true) + } else if repr < Self::MIN.0 { + (Self(repr | !Self::MAX.0), true) + } else { + (Self(repr), over) + } + } + + /// Creates a new integer from the underlying representation type. + /// + /// The returned tuple contains the new integer and a `bool` indicating if the representation + /// value overflowed the new integer. In the case of overflow, the new integer has a value + /// as if it were produced from [`new_wrapping`](Self::new_wrapping). + pub const fn new_overflowing(repr: i128) -> (Self, bool) { + Self::new_overflowing_impl((repr, false)) + } + + /// Returns the value of this integer as the underlying representation type. + pub const fn repr(self) -> i128 { + self.0 + } + + /// Returns `true` if this integer is less than zero. + pub const fn is_negative(self) -> bool { + (self.0 & Self::SIGN_BIT) != 0 + } + + /// Returns `true` if this integer is greater than zero. + pub const fn is_positive(self) -> bool { + self.0 != 0 && (self.0 & Self::SIGN_BIT) == 0 + } + + /// Returns the sign of the integer. + /// + /// * If `self < 0`, returns `-1` + /// * If `self > 0`, returns `1` + /// * If `self == 0`, returns `0` + pub const fn signum(self) -> Self { + if self.0 == 0 { + Self(0) + } else if self.0 > 0 { + Self(1) + } else { + Self(-1) + } + } + + /// Returns the number of ones in the binary representation of this integer. + pub const fn count_ones(self) -> u32 { + (self.0 & Self::MASK).count_ones() + } + + /// Returns the number of zeros in the binary representatino of this integer. + pub const fn count_zeros(self) -> u32 { + (self.0 | !Self::MASK).count_zeros() + } + + /// Returns the number of leading zeros in the binary represnetation of this integer. + pub const fn leading_zeros(self) -> u32 { + if self.is_negative() { + 0 + } else { + self.0.leading_zeros() - (i128::BITS - Self::BITS) + } + } + + /// Returns the number of trailing zeros in the binary representatino of this integer. + pub const fn trailing_zeros(self) -> u32 { + (self.0 | !Self::MASK).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of this integer. + pub const fn leading_ones(self) -> u32 { + (self.0 | !Self::MASK).leading_ones() - (i128::BITS - Self::BITS) + } + + /// Returns the number of trailing ones in the binary representation of this integer. + pub const fn trailing_ones(self) -> u32 { + (self.0 & Self::MASK).trailing_ones() + } + + /// Performs a left bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `<<` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_left(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping((self.0 << n) | ((self.0 & Self::MASK) >> (Self::BITS - n))) + } + + /// Performs a right bit shift by `n`, wrapping the truncated bits back to the end. + /// + /// Note that unlike the `>>` operator, all values of `n` are valid. A value of `n`, that + /// is greater than or equal to [`BITS`](Self::BITS), is the equivalent to using the value + /// `n % Self::BITS`. + pub const fn rotate_right(self, n: u32) -> Self { + let n = n % Self::BITS; + Self::new_wrapping(((self.0 & Self::MASK) >> n) | (self.0 << (Self::BITS - n))) + } + + /// Reverses the order of the bits in the binary representation of this integer. + pub const fn reverse_bits(self) -> Self { + Self(self.0.reverse_bits() >> (i128::BITS - Self::BITS)) + } + + /// Calculates the negative of this integer. + /// + /// This method works as a `const` capable alternative to `-self`. + pub const fn neg(self) -> Self { + debug_assert!(self.0 != Self::MIN.0, "attempt to negate with overflow"); + self.wrapping_neg() + } + + /// Calculates the sum of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self + rhs`. + pub const fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to add with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the difference of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self - rhs`. + pub const fn sub(self, rhs: Self) -> Self { + let val = self.0 - rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to subtract with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the product of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self * rhs`. + pub const fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to multiply with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self / rhs`. + pub const fn div(self, rhs: Self) -> Self { + let val = self.0 / rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self(val) + } + + /// Calculates the remainder of this integer over another integer. + /// + /// This method works as a `const` capable alternative to `self % rhs`. + pub const fn rem(self, rhs: Self) -> Self { + let val = self.0 % rhs.0; + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to calculate modulus with overflow" + ); + Self(val) + } + + /// Calculates the bitwise and of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self & rhs`. + pub const fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + + /// Calculates the bitwise or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self | rhs`. + pub const fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + + /// Calculates the bitwise exclusive-or of this integer with another integer. + /// + /// This method works as a `const` capable alternative to `self ^ rhs`. + pub const fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + + /// Calculates the bitwise negation of this integer. + /// + /// This method works as a `const` capable alternative to `!self`. + pub const fn not(self) -> Self { + Self(!self.0) + } + + /// Calculates the left bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self << rhs`. + pub const fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift left with overflow"); + Self::new_wrapping(self.0 << rhs) + } + + /// Calculates the right bitwise shift of this integer by `rhs`. + /// + /// This method works as a `const` capable alternative to `self >> rhs`. + pub const fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs >= Self::BITS, "attempt to shift right with overflow"); + Self::new_wrapping(self.0 >> rhs) + } + + /// Calculates the logarithm of this integer with respect to an arbitrary base, rounded + /// down. + /// + /// The [`ilog2`](Self::ilog2) and [`ilog10`](Self::ilog10) methods should be preferred + /// when applicable, as they are generally more optimized than this method since the base + /// of the logarithm is not arbitrary. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero, or if `base` is less + /// than 2. + pub const fn ilog(self, base: Self) -> u32 { + self.0.ilog(base.0) + } + + /// Calculates the base 2 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog2(self) -> u32 { + self.0.ilog2() + } + + /// Calculates the base 10 logarithm of this integer, rounded down. + /// + /// # Panics + /// This method will panic if `self` is less than or equal to zero. + pub const fn ilog10(self) -> u32 { + self.0.ilog10() + } + + /// Returns `true` if `self` and `rhs` are equal. + /// + /// This method works as a `const` capable alternative to `self == rhs`. + pub const fn eq(self, rhs: Self) -> bool { + return self.0 == rhs.0; + } + + /// Returns `true` if `self` and `rhs` are not equal. + /// + /// This method works as a `const` capable alternative to `self != rhs`. + pub const fn ne(self, rhs: Self) -> bool { + return self.0 != rhs.0; + } + + /// Returns `true` if `self` is less than `rhs`. + /// + /// This method works as a `const` capable alternative to `self < rhs`. + pub const fn lt(self, rhs: Self) -> bool { + return self.0 < rhs.0; + } + + /// Returns `true` if `self` is less than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self <= rhs`. + pub const fn le(self, rhs: Self) -> bool { + return self.0 <= rhs.0; + } + + /// Returns `true` if `self` is greater than `rhs`. + /// + /// This method works as a `const` capable alternative to `self > rhs`. + pub const fn gt(self, rhs: Self) -> bool { + return self.0 > rhs.0; + } + + /// Returns `true` if `self` is greater than or equal to `rhs`. + /// + /// This method works as a `const` capable alternative to `self >= rhs`. + pub const fn ge(self, rhs: Self) -> bool { + return self.0 >= rhs.0; + } + + /// Returns the ordering of `self` with respect to `rhs`. + /// + /// This method works as a `const` capable alternative to `Ord::cmp(self, rhs)`. + pub const fn cmp(self, rhs: Self) -> core::cmp::Ordering { + if self.0 < rhs.0 { + core::cmp::Ordering::Less + } else if self.0 > rhs.0 { + core::cmp::Ordering::Greater + } else { + core::cmp::Ordering::Equal + } + } + + /// Returns the minimum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::min(self, rhs)`. + pub const fn min(self, other: Self) -> Self { + if self.0 < other.0 { + self + } else { + other + } + } + + /// Returns the maximum of `self` and `other`. + /// + /// This method works as a `const` capable alternative to `Ord::max(self, rhs)`. + pub const fn max(self, other: Self) -> Self { + if self.0 > other.0 { + self + } else { + other + } + } + + /// Returns the value of this integer, clamped between `min` and `max`. + /// + /// This method works as a `const` capable alternative to `Ord::clamp(self, min, max)`. + pub const fn clamp(self, min: Self, max: Self) -> Self { + debug_assert!( + min.0 <= max.0, + "Attempt to clamp with minimum value greater than maximum value" + ); + Self::min(Self::max(self, min), max) + } + + /// Checked integer addition. Returns `None` if overflow occurred. + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer subtraction. Returns `None` if overflow occurred. + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer multiplication. Returns `None` if overflow occurred. + pub const fn checked_mul(self, rhs: Self) -> Option { + match self.0.checked_mul(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer division. Returns `None` if `rhs` is zero, or the division resulted in + /// overflow. + pub const fn checked_div(self, rhs: Self) -> Option { + match self.0.checked_div(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian division. Returns `None` if `rhs` is zero or `self.div_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + match self.0.checked_div_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer remainder. Returns `None` if `rhs` is zero or the remainder would have + /// resulted in overflow. + pub const fn checked_rem(self, rhs: Self) -> Option { + match self.0.checked_rem(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked euclidian remainder. Returns `None` if `rhs` is zero or `self.rem_euclid(rhs)` + /// would have resulted in overflow. + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + match self.0.checked_rem_euclid(rhs.0) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked integer negation. Returns `None` if the negation resulted in overflow. + pub const fn checked_neg(self) -> Option { + match self.0.checked_neg() { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked left bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shl(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shl(rhs)) + } + } + + /// Checked right bit shift. Returns `None` if `rhs` is greater than or equal to + /// [`Self::BITS`]. + pub const fn checked_shr(self, rhs: u32) -> Option { + if rhs >= Self::BITS { + None + } else { + Some(self.shr(rhs)) + } + } + + /// Checked exponentiation. Returns `None` if the exponentiation resulted in overflow. + pub const fn checked_pow(self, exp: u32) -> Option { + match self.0.checked_pow(exp) { + Some(val) => Self::new(val), + None => None, + } + } + + /// Checked logarithm, rounded down. Returns `None` if `self` is less than or equal zero, + /// or if `base` is less than 2. + pub const fn checked_ilog(self, base: Self) -> Option { + self.0.checked_ilog(base.0) + } + + /// Checked base 2 logarithm, rounded down. Returns `None` if self is less than or equal to + /// zero. + pub const fn checked_ilog2(self) -> Option { + self.0.checked_ilog2() + } + + /// Checked base 10 logarithm, rounded down. Returns `None` if self is less than or equal + /// to zero. + pub const fn checked_ilog10(self) -> Option { + self.0.checked_ilog10() + } + + /// Satruating integer addition. The result of the addition is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_add(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_add(rhs.0)) + } + + /// Saturating integer subtraction. The result of the subtraction is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_sub(rhs.0)) + } + + /// Saturating integer multiplication. The result of the multiplication is clamped between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_mul(self, rhs: Self) -> Self { + Self::new_saturating(self.0.saturating_mul(rhs.0)) + } + + /// Saturating exponentiation. The result of the exponentiation is clammed between + /// [`MIN`](Self::MIN) and [`MAX`](Self::MAX). + pub const fn saturating_pow(self, exp: u32) -> Self { + Self::new_saturating(self.0.saturating_pow(exp)) + } + + /// Wrapping (modular) addition. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_add(rhs.0)) + } + + /// Wrapping (modular) subtraction. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_sub(rhs.0)) + } + + /// Wrapping (modular) multiplication. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_mul(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_mul(rhs.0)) + } + + /// Wrapping (modular) division. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_div(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div(rhs.0)) + } + + /// Wrapping (modular) euclidian division. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_div_euclid(rhs.0)) + } + + /// Wrapping (modular) remainder. An overflowing result is wrapped around the bounds of + /// this integer type. + pub const fn wrapping_rem(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem(rhs.0)) + } + + /// Wrapping (modular) euclidian remainder. An overflowing result is wrapped around the + /// bounds of this integer type. + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.wrapping_rem_euclid(rhs.0)) + } + + /// Wrapping (modular) negation. An overflowing result is wrapped around the bounds of this + /// integer type. + pub const fn wrapping_neg(self) -> Self { + Self::new_wrapping(!self.0 + 1) + } + + /// Wrapping (modular) left bit shift. The value is left shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shl(self, rhs: u32) -> Self { + Self::new_wrapping(self.0 << (rhs % Self::BITS)) + } + + /// Wrapping (modular) right bit shift. The value is right shifted `rhs % Self::BITS` bits. + pub const fn wrapping_shr(self, rhs: u32) -> Self { + Self::new_wrapping((self.0 & Self::MASK) >> (rhs % Self::BITS)) + } + + /// Wrapping (modular) exponentiation. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_pow(self, exp: u32) -> Self { + Self::new_wrapping(self.0.wrapping_pow(exp)) + } + + /// Wrapping (modular) aboslute value. An overflowing result is wrapped around the bounds + /// of this integer type. + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Calculates `self + rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_add(rhs.0)) + } + + /// Calculates `self - rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_sub(rhs.0)) + } + + /// Calculates `self * rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_mul(rhs.0)) + } + + /// Calculates `self / rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div(rhs.0)) + } + + /// Calculates `self.div_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_div_euclid(rhs.0)) + } + + /// Calculates `self % rhs`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem(rhs.0)) + } + + /// Calculates `self.rem_euclid(rhs)`, returning a tuple of the result and a `bool` + /// indicating if overflow occurred. + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_rem_euclid(rhs.0)) + } + + /// Calculates `-self`, returning a tuple of the result and a `bool` indicating if overflow + /// occurred. + pub const fn overflowing_neg(self) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_neg()) + } + + /// Calculates `self << rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Calculates `self >> rhs`, returning a tuple of the result and a `bool` indicating if + /// `rhs` was greater than or equal to [`Self::BITS`]. + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Calculates `self.pow(exp)`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::new_overflowing_impl(self.0.overflowing_pow(exp)) + } + + /// Calculates `self.abs()`, returning a tuple of the result and a `bool` indicating if + /// overflow occurred. + pub const fn overflowing_abs(self) -> (Self, bool) { + if self.is_negative() { + self.overflowing_neg() + } else { + (self, false) + } + } + + /// Raises `self` to the power of `exp`, using exponentiation by squaring. + pub const fn pow(self, exp: u32) -> Self { + let val = self.0.pow(exp); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to exponentiate with overflow" + ); + Self::new_wrapping(val) + } + + /// Calculates the quotient of Euclidian division `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with `r = + /// self.rem_euclid(rhs)` and `0 <= r < rhs.abs()`. + /// + /// In other words, the result is `self / rhs`, rounded to the integer `q` such that `self + /// >= q * rhs`. If `self > 0`, this is equal to round towards zero. If `self < 0`, this is + /// equal to rounds towards +/- infinity. + pub const fn div_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Calculates the non-negative remainder `self (mod rhs)`. + /// + /// This is done as if by the Euclidian division algorithm - given `r = + /// self.rem_euclid(rhs)`, `self = self * self.div_euclid(rhs) + r`, and `0 <= r < + /// r.abs()`. + pub const fn rem_euclid(self, rhs: Self) -> Self { + Self::new_wrapping(self.0.div_euclid(rhs.0)) + } + + /// Computes the absolute value of this integer. + pub const fn abs(self) -> Self { + debug_assert!( + self.0 != Self::MIN.0, + "attempt to calculate absolute value with overflow" + ); + self.wrapping_abs() + } + + /// Computes the absolute difference between `self` and `rhs`. + /// + /// This is equivalent to `(self - rhs).abs()` without the posibility of intermediate + /// overflow. + pub const fn abs_diff(self, rhs: Self) -> Aint { + Aint(self.0.abs_diff(rhs.0)) + } + + /// Converts a string slice in a given base (`radix`) to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading + /// and trailing whitespace will result in an error. Digits are a subset of the following + /// characters depending on the `radix`. + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// This function panics if `radix` is not in the range from 2 to 36. + pub fn from_str_radix(src: &str, radix: u32) -> Result { + Self::new(i128::from_str_radix(src, radix)?).ok_or_else(make_parse_int_err) + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 56) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 9]) -> Self { + Self(i128::from_be_bytes([ + 0, 0, 0, 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], + bytes[6], bytes[7], bytes[8], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 9]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], 0, 0, 0, 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 9]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 9] { + let tmp = self.0.to_be_bytes(); + [ + tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 9] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 9] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 48) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 10]) -> Self { + Self(i128::from_be_bytes([ + 0, 0, 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 10]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], 0, 0, 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 10]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 10] { + let tmp = self.0.to_be_bytes(); + [ + tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 10] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 10] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 40) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 11]) -> Self { + Self(i128::from_be_bytes([ + 0, 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], bytes[10], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 11]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], 0, 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 11]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 11] { + let tmp = self.0.to_be_bytes(); + [ + tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], + tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 11] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 11] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 32) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 12]) -> Self { + Self(i128::from_be_bytes([ + 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 12]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], 0, 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 12]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 12] { + let tmp = self.0.to_be_bytes(); + [ + tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], + tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 12] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 12] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 24) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 13]) -> Self { + Self(i128::from_be_bytes([ + 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 13]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], 0, 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 13]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 13] { + let tmp = self.0.to_be_bytes(); + [ + tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], + tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 13] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], tmp[12], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 13] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 16) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 14]) -> Self { + Self(i128::from_be_bytes([ + 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 14]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], 0, 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 14]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 14] { + let tmp = self.0.to_be_bytes(); + [ + tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], + tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 14] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], tmp[12], tmp[13], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 14] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} + +impl Aint { + /// Reverses the byte order of the integer. + pub const fn swap_bytes(self) -> Self { + Self((self.0.swap_bytes() >> 8) & Self::MASK) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(target_endian = "little")] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(target_endian = "big")] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + pub const fn to_be(self) -> Self { + #[cfg(target_endian = "big")] + { + self + } + #[cfg(target_endian = "little")] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(target_endian = "big")] + { + self.swap_bytes() + } + } + + /// Creates an integer value from its memory representation as a byte array in bit endian. + pub const fn from_be_bytes(bytes: [u8; 15]) -> Self { + Self(i128::from_be_bytes([ + 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], + ])) + } + + /// Creates an integer value from its memory representation as a byte array in little endian. + pub const fn from_le_bytes(bytes: [u8; 15]) -> Self { + Self(i128::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], 0, + ])) + } + + /// Creates an integer value from its memory representation as a byte array in native + /// endianness. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`from_be_bytes`](Self::from_be_bytes) or [`from_le_bytes`](Self::from_le_bytes), + /// as appropriate instead. + pub const fn from_ne_bytes(bytes: [u8; 15]) -> Self { + #[cfg(target_endian = "big")] + { + Self::from_be_bytes(bytes) + } + #[cfg(target_endian = "little")] + { + Self::from_le_bytes(bytes) + } + } + + /// Return the memory representation of this integer as a byte array in big-endian byte + /// order. + pub const fn to_be_bytes(self) -> [u8; 15] { + let tmp = self.0.to_be_bytes(); + [ + tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], + tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + ] + } + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + pub const fn to_le_bytes(self) -> [u8; 15] { + let tmp = self.0.to_le_bytes(); + [ + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], + tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], + ] + } + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + /// + /// As the target platform's native endianness is used, portable code likely wants to + /// use [`to_be_bytes`](Self::to_be_bytes) or [`to_le_bytes`](Self::to_le_bytes), as + /// appropriate instead. + pub const fn to_ne_bytes(self) -> [u8; 15] { + #[cfg(target_endian = "big")] + { + self.to_be_bytes() + } + #[cfg(target_endian = "little")] + { + self.to_le_bytes() + } + } +} diff --git a/src/bit_concat.rs b/src/bit_concat.rs new file mode 100644 index 0000000..b231203 --- /dev/null +++ b/src/bit_concat.rs @@ -0,0 +1,26 @@ +use crate::{int::Int, width, WrappingInto}; + +/// Concatenate two integral types bitwise into a larger integral type. +/// +/// # Example: +/// ``` +/// # use aint::BitConcat; +/// let concat = u16::bit_concat(0b10101010u8, 0b01010101u8); +/// assert_eq!(concat, 0b10101010_01010101_u16); +/// ``` +pub trait BitConcat: Sized { + fn bit_concat(left: L, right: R) -> Self; +} + +impl BitConcat for T +where + ::Add: width::WidthEq, + L: WrappingInto, + R: WrappingInto, +{ + fn bit_concat(left: L, right: R) -> Self { + let l: Self = left.wrapping_into(); + let r: Self = right.wrapping_into(); + (l << R::BITS) | r + } +} diff --git a/src/bit_split.rs b/src/bit_split.rs new file mode 100644 index 0000000..36d8c69 --- /dev/null +++ b/src/bit_split.rs @@ -0,0 +1,24 @@ +use crate::{int::Int, width, WrappingInto}; + +/// Split an integral type bitwise into two smaller integral types. +/// +/// # Example: +/// ``` +/// # use aint::BitSplit; +/// let (upper, lower): (u8, u8) = 0b10101010_01010101_u16.bit_split(); +/// assert_eq!(upper, 0b10101010); +/// assert_eq!(lower, 0b01010101); +/// ``` +pub trait BitSplit: Sized { + fn bit_split(self) -> (L, R); +} + +impl BitSplit for T +where + ::Add: width::WidthEq, + T: WrappingInto + WrappingInto, +{ + fn bit_split(self) -> (L, R) { + ((self >> R::BITS).wrapping_into(), self.wrapping_into()) + } +} diff --git a/src/convs.rs b/src/convs.rs new file mode 100644 index 0000000..97b3c0c --- /dev/null +++ b/src/convs.rs @@ -0,0 +1,2255 @@ +use crate::Aint; + +fn make_try_from_int_err() -> core::num::TryFromIntError { + let val: i8 = -1; + let Err(e) = u8::try_from(val) else { + unreachable!() + }; + e +} + +impl From for Aint { + fn from(value: bool) -> Self { + Self(if value { 1 } else { 0 }) + } +} + +impl From> for bool { + fn from(value: Aint) -> Self { + value.0 != 0 + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u8) -> Result { + if value <= Self::MAX.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u16) -> Result { + if value <= Self::MAX.0 as u16 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u32) -> Result { + if value <= Self::MAX.0 as u32 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i8) -> Result { + if value >= 0 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value >= 0 && value <= Self::MAX.0 as i16 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value >= 0 && value <= Self::MAX.0 as i32 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value >= 0 && value <= Self::MAX.0 as i64 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value >= 0 && value <= Self::MAX.0 as i128 { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: isize) -> Result { + if value >= 0 && value <= Self::MAX.0 as isize { + Ok(Self(value as u8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl From> for u8 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for u16 { + fn from(value: Aint) -> Self { + value.0 as u16 + } +} + +impl From> for u32 { + fn from(value: Aint) -> Self { + value.0 as u32 + } +} + +impl From> for u64 { + fn from(value: Aint) -> Self { + value.0 as u64 + } +} + +impl From> for u128 { + fn from(value: Aint) -> Self { + value.0 as u128 + } +} + +impl From> for usize { + fn from(value: Aint) -> Self { + value.0 as usize + } +} + +impl From> for i8 { + fn from(value: Aint) -> Self { + value.0 as i8 + } +} + +impl From> for i16 { + fn from(value: Aint) -> Self { + value.0 as i16 + } +} + +impl From> for i32 { + fn from(value: Aint) -> Self { + value.0 as i32 + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl From> for isize { + fn from(value: Aint) -> Self { + value.0 as isize + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as u16) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u16) -> Result { + if value <= Self::MAX.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u32) -> Result { + if value <= Self::MAX.0 as u32 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i8) -> Result { + if value >= 0 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value >= 0 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value >= 0 && value <= Self::MAX.0 as i32 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value >= 0 && value <= Self::MAX.0 as i64 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value >= 0 && value <= Self::MAX.0 as i128 { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: isize) -> Result { + if value >= 0 && value <= Self::MAX.0 as isize { + Ok(Self(value as u16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for u16 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for u32 { + fn from(value: Aint) -> Self { + value.0 as u32 + } +} + +impl From> for u64 { + fn from(value: Aint) -> Self { + value.0 as u64 + } +} + +impl From> for u128 { + fn from(value: Aint) -> Self { + value.0 as u128 + } +} + +impl From> for usize { + fn from(value: Aint) -> Self { + value.0 as usize + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i16 { + fn from(value: Aint) -> Self { + value.0 as i16 + } +} + +impl From> for i32 { + fn from(value: Aint) -> Self { + value.0 as i32 + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl From> for isize { + fn from(value: Aint) -> Self { + value.0 as isize + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as u32) + } +} + +impl From for Aint { + fn from(value: u16) -> Self { + Self(value as u32) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u32) -> Result { + if value <= Self::MAX.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(target_pointer_width = "16")] + fn try_from(value: usize) -> Result { + Ok(Self(value as u32)) + } + + #[cfg(not(target_pointer_width = "16"))] + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i8) -> Result { + if value >= 0 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value >= 0 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value >= 0 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value >= 0 && value <= Self::MAX.0 as i64 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value >= 0 && value <= Self::MAX.0 as i128 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(target_pointer_width = "16")] + fn try_from(value: isize) -> Result { + if value >= 0 { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } + + #[cfg(not(target_pointer_width = "16"))] + fn try_from(value: isize) -> Result { + if value >= 0 && value <= Self::MAX.0 as isize { + Ok(Self(value as u32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for u32 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for u64 { + fn from(value: Aint) -> Self { + value.0 as u64 + } +} + +impl From> for u128 { + fn from(value: Aint) -> Self { + value.0 as u128 + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i32 { + fn from(value: Aint) -> Self { + value.0 as i32 + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl TryFrom> for isize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as u64) + } +} + +impl From for Aint { + fn from(value: u16) -> Self { + Self(value as u64) + } +} + +impl From for Aint { + fn from(value: u32) -> Self { + Self(value as u64) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + fn try_from(value: usize) -> Result { + Ok(Self(value as u64)) + } + + #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i8) -> Result { + if value >= 0 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value >= 0 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value >= 0 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value >= 0 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value >= 0 && value <= Self::MAX.0 as i128 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + fn try_from(value: isize) -> Result { + if value >= 0 { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } + + #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] + fn try_from(value: isize) -> Result { + if value >= 0 && value <= Self::MAX.0 as isize { + Ok(Self(value as u64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for u64 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for u128 { + fn from(value: Aint) -> Self { + value.0 as u128 + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl TryFrom> for isize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as u128) + } +} + +impl From for Aint { + fn from(value: u16) -> Self { + Self(value as u128) + } +} + +impl From for Aint { + fn from(value: u32) -> Self { + Self(value as u128) + } +} + +impl From for Aint { + fn from(value: u64) -> Self { + Self(value as u128) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + ))] + fn try_from(value: usize) -> Result { + Ok(Self(value as u128)) + } + + #[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + )))] + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i8) -> Result { + if value >= 0 { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value >= 0 { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value >= 0 { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value >= 0 { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value >= 0 { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + ))] + fn try_from(value: isize) -> Result { + if value >= 0 { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } + + #[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + )))] + fn try_from(value: isize) -> Result { + if value >= 0 && value <= Self::MAX.0 as isize { + Ok(Self(value as u128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for u128 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl TryFrom> for isize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u8) -> Result { + if value <= Self::MAX.0 as u8 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u16) -> Result { + if value <= Self::MAX.0 as u16 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u32) -> Result { + if value <= Self::MAX.0 as u32 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i8) -> Result { + if value <= Self::MAX.0 && value >= Self::MIN.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value <= Self::MAX.0 as i16 && value >= Self::MIN.0 as i16 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value <= Self::MAX.0 as i32 && value >= Self::MIN.0 as i32 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value <= Self::MAX.0 as i64 && value >= Self::MIN.0 as i64 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value <= Self::MAX.0 as i128 && value >= Self::MIN.0 as i128 { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: isize) -> Result { + if value <= Self::MAX.0 as isize && value >= Self::MIN.0 as isize { + Ok(Self(value as i8)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u128 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i8 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for i16 { + fn from(value: Aint) -> Self { + value.0 as i16 + } +} + +impl From> for i32 { + fn from(value: Aint) -> Self { + value.0 as i32 + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl From> for isize { + fn from(value: Aint) -> Self { + value.0 as isize + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as i16) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u16) -> Result { + if value <= Self::MAX.0 as u16 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u32) -> Result { + if value <= Self::MAX.0 as u32 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl From for Aint { + fn from(value: i8) -> Self { + Self(value as i16) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i16) -> Result { + if value <= Self::MAX.0 && value >= Self::MIN.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value <= Self::MAX.0 as i32 && value >= Self::MIN.0 as i32 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value <= Self::MAX.0 as i64 && value >= Self::MIN.0 as i64 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value <= Self::MAX.0 as i128 && value >= Self::MIN.0 as i128 { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: isize) -> Result { + if value <= Self::MAX.0 as isize && value >= Self::MIN.0 as isize { + Ok(Self(value as i16)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u128 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i16 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for i32 { + fn from(value: Aint) -> Self { + value.0 as i32 + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl From> for isize { + fn from(value: Aint) -> Self { + value.0 as isize + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as i32) + } +} + +impl From for Aint { + fn from(value: u16) -> Self { + Self(value as i32) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u32) -> Result { + if value <= Self::MAX.0 as u32 { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(target_pointer_width = "16")] + fn try_from(value: usize) -> Result { + Ok(Self(value as i32)) + } + + #[cfg(not(target_pointer_width = "16"))] + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl From for Aint { + fn from(value: i8) -> Self { + Self(value as i32) + } +} + +impl From for Aint { + fn from(value: i16) -> Self { + Self(value as i32) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i32) -> Result { + if value <= Self::MAX.0 && value >= Self::MIN.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value <= Self::MAX.0 as i64 && value >= Self::MIN.0 as i64 { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value <= Self::MAX.0 as i128 && value >= Self::MIN.0 as i128 { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(target_pointer_width = "16")] + fn try_from(value: isize) -> Result { + Ok(Self(value as i32)) + } + + #[cfg(not(target_pointer_width = "16"))] + fn try_from(value: isize) -> Result { + if value <= Self::MAX.0 as isize && value >= Self::MIN.0 as isize { + Ok(Self(value as i32)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u128 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i32 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 as i64 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl TryFrom> for isize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as i64) + } +} + +impl From for Aint { + fn from(value: u16) -> Self { + Self(value as i64) + } +} + +impl From for Aint { + fn from(value: u32) -> Self { + Self(value as i64) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u64) -> Result { + if value <= Self::MAX.0 as u64 { + Ok(Self(value as i64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as i64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + fn try_from(value: usize) -> Result { + Ok(Self(value as i64)) + } + + #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as i64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl From for Aint { + fn from(value: i8) -> Self { + Self(value as i64) + } +} + +impl From for Aint { + fn from(value: i16) -> Self { + Self(value as i64) + } +} + +impl From for Aint { + fn from(value: i32) -> Self { + Self(value as i64) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i64) -> Result { + if value <= Self::MAX.0 && value >= Self::MIN.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value <= Self::MAX.0 as i128 && value >= Self::MIN.0 as i128 { + Ok(Self(value as i64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + fn try_from(value: isize) -> Result { + Ok(Self(value as i64)) + } + + #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] + fn try_from(value: isize) -> Result { + if value <= Self::MAX.0 as isize && value >= Self::MIN.0 as isize { + Ok(Self(value as i64)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u128 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i64 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 as i128 + } +} + +impl TryFrom> for isize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From for Aint { + fn from(value: u8) -> Self { + Self(value as i128) + } +} + +impl From for Aint { + fn from(value: u16) -> Self { + Self(value as i128) + } +} + +impl From for Aint { + fn from(value: u32) -> Self { + Self(value as i128) + } +} + +impl From for Aint { + fn from(value: u64) -> Self { + Self(value as i128) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: u128) -> Result { + if value <= Self::MAX.0 as u128 { + Ok(Self(value as i128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + ))] + fn try_from(value: usize) -> Result { + Ok(Self(value as i128)) + } + + #[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + )))] + fn try_from(value: usize) -> Result { + if value <= Self::MAX.0 as usize { + Ok(Self(value as i128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl From for Aint { + fn from(value: i8) -> Self { + Self(value as i128) + } +} + +impl From for Aint { + fn from(value: i16) -> Self { + Self(value as i128) + } +} + +impl From for Aint { + fn from(value: i32) -> Self { + Self(value as i128) + } +} + +impl From for Aint { + fn from(value: i64) -> Self { + Self(value as i128) + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + fn try_from(value: i128) -> Result { + if value <= Self::MAX.0 && value >= Self::MIN.0 { + Ok(Self(value)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom for Aint { + type Error = core::num::TryFromIntError; + + #[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + ))] + fn try_from(value: isize) -> Result { + Ok(Self(value as i128)) + } + + #[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + )))] + fn try_from(value: isize) -> Result { + if value <= Self::MAX.0 as isize && value >= Self::MIN.0 as isize { + Ok(Self(value as i128)) + } else { + Err(make_try_from_int_err()) + } + } +} + +impl TryFrom> for u8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for u128 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for usize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i8 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i16 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i32 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl TryFrom> for i64 { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} + +impl From> for i128 { + fn from(value: Aint) -> Self { + value.0 + } +} + +impl TryFrom> for isize { + type Error = core::num::TryFromIntError; + + fn try_from(value: Aint) -> Result { + value.0.try_into() + } +} diff --git a/src/int.rs b/src/int.rs new file mode 100644 index 0000000..22e1ffc --- /dev/null +++ b/src/int.rs @@ -0,0 +1,214 @@ +use crate::non_prim::NonPrim; +use crate::tybit; +use crate::width; + +pub trait Int: + core::fmt::Debug + + core::fmt::Display + + core::fmt::Octal + + core::fmt::Binary + + core::fmt::UpperHex + + core::fmt::LowerHex + + Clone + + Copy + + PartialEq + + Eq + + PartialOrd + + Ord + + core::hash::Hash + + core::ops::Add + + core::ops::Sub + + core::ops::Mul + + core::ops::Div + + core::ops::Rem + + core::ops::BitAnd + + core::ops::BitOr + + core::ops::BitXor + + core::ops::Not + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::AddAssign + + core::ops::SubAssign + + core::ops::MulAssign + + core::ops::DivAssign + + core::ops::RemAssign + + core::ops::BitAndAssign + + core::ops::BitOrAssign + + core::ops::BitXorAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign +{ + const SIGNED: bool; + const BITS: u32; + const ZERO: Self; + const ONE: Self; + const MIN: Self; + const MAX: Self; + type Signed: tybit::Bit; + type Width: width::Width; +} + +impl Int for u8 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<8>; +} + +impl Int for u16 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<16>; +} + +impl Int for u32 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<32>; +} + +impl Int for u64 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<64>; +} + +impl Int for u128 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<128>; +} + +impl Int for i8 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<8>; +} + +impl Int for i16 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<16>; +} + +impl Int for i32 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<32>; +} + +impl Int for i64 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<64>; +} + +impl Int for i128 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<128>; +} + +impl Int for T { + const SIGNED: bool = ::SIGNED; + const BITS: u32 = ::BITS; + const ZERO: Self = ::ZERO; + const ONE: Self = ::ONE; + const MIN: Self = ::MIN; + const MAX: Self = ::MAX; + type Signed = ::Signed; + type Width = ::Width; +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..3a4425a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,150 @@ +#![no_std] + +//! Aint is a crate implementing integers of non-standard bit widths between +//! 1 and 127. These integer types are represented by the next largest built-in +//! Rust integer, but are bounded to the range and behaviors of the advertised +//! bit width. That is, `T::MIN` and `T::MAX`, are what would be expected for +//! the integer `T` with `N` bits, and similarly, wrapping, saturating, and +//! overflow behaviors match what would be expected for a hypothetical built-in +//! integer `T` with `N` bits. +//! +//! # Example +//! ``` +//! # use aint::*; +//! fn add(a: i13, b: i13) -> i13 { +//! a + b +//! } +//! +//! let x = i13!(100); +//! let y = add(x, i13!(-42)); +//! assert_eq!(y, i13!(58)); +//! ``` +//! +//! The core implementation type is [`Aint`](Aint), which +//! accepts a representation type, `R`, and a bit width, `WIDTH`. [`Aint`] is +//! intended to primarily be an implementation detail, not to be used directly. +//! Instead, it is preferred to use the type aliases provided by this crate. +//! +//! If [`Aint`] is used directly, it will only permit generic parameters that +//! match one of the existing type aliases provided by this crate. For example, +//! the type [`i24`](type@i24) is an alias of `Aint`. In theory, +//! `Aint` would be equivalent in functionality, but will result in a +//! compile time error if instantiated. This prevents the existence multiple +//! [`Aint`]s that are functionally the same but are incompatible types to the +//! compiler. +//! +//! # Byte Wide Types +//! Integer types that have an exact byte width provide additional methods and +//! functionality that other integer types do not. These are types whose width +//! is a multiple of 8, such as [`i24`](type@i24) (3 bytes), [`u56`](type@u56) +//! (7 bytes), and [`u120`](type@u120) (15 bytes). Such types provide the byte +//! and endianness manipulation APIs that built-in Rust integers provide, such +//! as `T::from_be_bytes`, `T::swap_bytes`, and `T::to_le`. Other integer types +//! do not implement these methods since their meaning becomes ambiguous or +//! perhaps even nonsensical. +//! +//! # Conversions +//! All integer types provided by this crate implement traits to convert to and +//! from all built-in Rust integer types. A conversion will be implemented as +//! [`From`] when the conversion is infallible, and [`TryFrom`] when the +//! conversion can fail. For example, converting from [`i4`](type@i4) to +//! [`i8`](prim@i8) is implemented as `impl From for i8`, but the reverse +//! conversion is implemented as `impl TryFrom for i4`. +//! +//! Unfortunately, this crate does not provide the same conversions between +//! each of the pairs of types provided, such as [`i4`](type@i4) to +//! [`i13`](type@i13). Existing blanket implmentations on the standard conversion +//! traits prevent a generic implementation of these traits that would cover all +//! the types provided by this crate, and implementing conversions for each pair +//! of types individually is infeasible due to extreme compiliation times, since +//! each pair would result on the order of 1282 trait implementations. +//! +//! This crate also provides two alternate conversion traits that perform +//! infallible, but potentially lossy, conversions: +//! [`WrappingFrom`]/[`WrappingInto`] and [`SaturatingFrom`]/[`SaturatingInto`]. +//! These are implemented for all combinations of built-in integers and integers +//! provided by this crate. See each trait's documentation for more details. +//! +//! # Concatenation and Splitting +//! This crate also provides two traits for concatenating and spliting integers +//! bitwise: [`BitConcat`] and [`BitSplit`]. Any pair of two integer types can +//! be concatenated as long as their combined bit width is at most 128, and +//! any integer can be split bitwise into any two integers whose combined bit +//! width equals the bit width of the original integer. +//! +//! ``` +//! # use aint::*; +//! let x: u16 = 0b0101010100101_101; +//! let (x1, x2): (i13, u3) = x.bit_split(); +//! let y = u16::bit_concat(x1, x2); +//! +//! assert_eq!(x, y); +//! assert_eq!(x1, i13!(0b0101010100101)); +//! assert_eq!(x2, u3!(0b101)); +//! ``` +//! +//! # Macros +//! Each integer type provided by this crate comes with macro for constructing +//! these types from literals. Built-in integers can have typed literals, such +//! as `42u8` or `-7i64`. The macros provided by this crate perform a similar +//! function. `u13!(100)` is essentially a [`u13`](type@u13) literal with the +//! value `100`. The values provided to these macros are also checked at compile +//! time to ensure that they are valid for the type. For example, `u4!(100)`, +//! would result in a compile time error, because [`u4`](type@u4) can only +//! represent values from `0` to `15`, inclusive. +//! +//! # Features +//! This crate has two non-default features, `serde` and `num`, which enable +//! compaitbility with the `serde` and `num` crates. +//! +//! Enabling the `serde` feature will provide implementations of +//! [`serde::Serialize`](::serde::Serialize) and +//! [`serde::Deserialize`](::serde::Deserialize) for each integer type in +//! this crate. +//! +//! Enabling the `num` feature will provide implementations of all appropriate +//! traits from the [`num_traits`] and [`num_integer`] crates under the `num` +//! family of crates. +//! +//! ```toml +//! [dependencies] +//! aint = { version = "0.1", features = [ "serde", "num" ] } +//! ``` +//! +//! # `no_std` +//! This crate is also `#![no_std]`. Unlike some other crates, this crate does +//! not have a `std` (or `no_std`) feature - it simply never uses or needs +//! `libstd`. Additionally, this crate does not use `alloc` either. `libcore` +//! is the only required dependency, and the crates pulled in by the `serde` +//! and `num` features are also `no_std` compatible. + +mod aint; +mod bit_concat; +mod bit_split; +mod convs; +pub(crate) mod int; +mod macros; +mod misc; +pub(crate) mod non_prim; +#[cfg(feature = "num")] +mod num; +mod ops; +pub(crate) mod prim; +mod saturating; +pub(crate) mod sealed; +#[cfg(feature = "serde")] +mod serde; +mod shifts; +#[cfg(test)] +mod test; +pub(crate) mod tybit; +mod typedefs; +pub(crate) mod width; +mod wrapping; + +pub use aint::*; +pub use bit_concat::*; +pub use bit_split::*; +pub use saturating::*; +pub use typedefs::*; +pub use wrapping::*; diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..99e06d5 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,434 @@ +#[allow(unused_imports)] +use crate::*; + +/// Returns a [`u8`](type@crate::u8) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = u8!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! u8 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: u8 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`u16`](type@crate::u16) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = u16!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! u16 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: u16 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`u32`](type@crate::u32) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = u32!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! u32 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: u32 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`u64`](type@crate::u64) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = u64!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! u64 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: u64 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`u128`](type@crate::u128) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = u128!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! u128 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: u128 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`i8`](type@crate::i8) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = i8!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! i8 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: i8 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`i16`](type@crate::i16) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = i16!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! i16 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: i16 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`i32`](type@crate::i32) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = i32!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! i32 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: i32 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`i64`](type@crate::i64) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = i64!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! i64 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: i64 = $val; + __AINT_LITERAL_VALUE + }}; +} + +/// Returns a [`i128`](type@crate::i128) checked at compile time. +/// +/// # Example +/// ``` +/// # use aint::*; +/// let x = i128!(42); +/// assert_eq!(x, 42); +/// ``` +#[macro_export] +macro_rules! i128 { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: i128 = $val; + __AINT_LITERAL_VALUE + }}; +} + +macro_rules! lit_macro { + ($ty:ident) => { + #[doc=core::concat!("Returns a [`", core::stringify!($ty), "`](type@", core::stringify!($ty), ") checked at compile time.")] + #[doc=""] + #[doc="# Example"] + #[doc="```"] + #[doc="# use aint::*;"] + #[doc=core::concat!("let x = ", core::stringify!($ty), "!(0);")] + #[doc="assert_eq!(x.repr(), 0);"] + #[doc="```"] + #[macro_export] + macro_rules! $ty { + ($val:literal) => {{ + const __AINT_LITERAL_VALUE: $ty = match $crate::$ty::new($val) { + Some(__aint_literal_value) => __aint_literal_value, + None => ::core::panic!(::core::concat!("Invalid value for ", ::core::stringify!($ty))), + }; + __AINT_LITERAL_VALUE + }}; + } + }; +} + +lit_macro!(bit); +lit_macro!(u1); +lit_macro!(u2); +lit_macro!(u3); +lit_macro!(u4); +lit_macro!(u5); +lit_macro!(u6); +lit_macro!(u7); +lit_macro!(u9); +lit_macro!(u10); +lit_macro!(u11); +lit_macro!(u12); +lit_macro!(u13); +lit_macro!(u14); +lit_macro!(u15); +lit_macro!(u17); +lit_macro!(u18); +lit_macro!(u19); +lit_macro!(u20); +lit_macro!(u21); +lit_macro!(u22); +lit_macro!(u23); +lit_macro!(u24); +lit_macro!(u25); +lit_macro!(u26); +lit_macro!(u27); +lit_macro!(u28); +lit_macro!(u29); +lit_macro!(u30); +lit_macro!(u31); +lit_macro!(u33); +lit_macro!(u34); +lit_macro!(u35); +lit_macro!(u36); +lit_macro!(u37); +lit_macro!(u38); +lit_macro!(u39); +lit_macro!(u40); +lit_macro!(u41); +lit_macro!(u42); +lit_macro!(u43); +lit_macro!(u44); +lit_macro!(u45); +lit_macro!(u46); +lit_macro!(u47); +lit_macro!(u48); +lit_macro!(u49); +lit_macro!(u50); +lit_macro!(u51); +lit_macro!(u52); +lit_macro!(u53); +lit_macro!(u54); +lit_macro!(u55); +lit_macro!(u56); +lit_macro!(u57); +lit_macro!(u58); +lit_macro!(u59); +lit_macro!(u60); +lit_macro!(u61); +lit_macro!(u62); +lit_macro!(u63); +lit_macro!(u65); +lit_macro!(u66); +lit_macro!(u67); +lit_macro!(u68); +lit_macro!(u69); +lit_macro!(u70); +lit_macro!(u71); +lit_macro!(u72); +lit_macro!(u73); +lit_macro!(u74); +lit_macro!(u75); +lit_macro!(u76); +lit_macro!(u77); +lit_macro!(u78); +lit_macro!(u79); +lit_macro!(u80); +lit_macro!(u81); +lit_macro!(u82); +lit_macro!(u83); +lit_macro!(u84); +lit_macro!(u85); +lit_macro!(u86); +lit_macro!(u87); +lit_macro!(u88); +lit_macro!(u89); +lit_macro!(u90); +lit_macro!(u91); +lit_macro!(u92); +lit_macro!(u93); +lit_macro!(u94); +lit_macro!(u95); +lit_macro!(u96); +lit_macro!(u97); +lit_macro!(u98); +lit_macro!(u99); +lit_macro!(u100); +lit_macro!(u101); +lit_macro!(u102); +lit_macro!(u103); +lit_macro!(u104); +lit_macro!(u105); +lit_macro!(u106); +lit_macro!(u107); +lit_macro!(u108); +lit_macro!(u109); +lit_macro!(u110); +lit_macro!(u111); +lit_macro!(u112); +lit_macro!(u113); +lit_macro!(u114); +lit_macro!(u115); +lit_macro!(u116); +lit_macro!(u117); +lit_macro!(u118); +lit_macro!(u119); +lit_macro!(u120); +lit_macro!(u121); +lit_macro!(u122); +lit_macro!(u123); +lit_macro!(u124); +lit_macro!(u125); +lit_macro!(u126); +lit_macro!(u127); + +lit_macro!(i1); +lit_macro!(i2); +lit_macro!(i3); +lit_macro!(i4); +lit_macro!(i5); +lit_macro!(i6); +lit_macro!(i7); +lit_macro!(i9); +lit_macro!(i10); +lit_macro!(i11); +lit_macro!(i12); +lit_macro!(i13); +lit_macro!(i14); +lit_macro!(i15); +lit_macro!(i17); +lit_macro!(i18); +lit_macro!(i19); +lit_macro!(i20); +lit_macro!(i21); +lit_macro!(i22); +lit_macro!(i23); +lit_macro!(i24); +lit_macro!(i25); +lit_macro!(i26); +lit_macro!(i27); +lit_macro!(i28); +lit_macro!(i29); +lit_macro!(i30); +lit_macro!(i31); +lit_macro!(i33); +lit_macro!(i34); +lit_macro!(i35); +lit_macro!(i36); +lit_macro!(i37); +lit_macro!(i38); +lit_macro!(i39); +lit_macro!(i40); +lit_macro!(i41); +lit_macro!(i42); +lit_macro!(i43); +lit_macro!(i44); +lit_macro!(i45); +lit_macro!(i46); +lit_macro!(i47); +lit_macro!(i48); +lit_macro!(i49); +lit_macro!(i50); +lit_macro!(i51); +lit_macro!(i52); +lit_macro!(i53); +lit_macro!(i54); +lit_macro!(i55); +lit_macro!(i56); +lit_macro!(i57); +lit_macro!(i58); +lit_macro!(i59); +lit_macro!(i60); +lit_macro!(i61); +lit_macro!(i62); +lit_macro!(i63); +lit_macro!(i65); +lit_macro!(i66); +lit_macro!(i67); +lit_macro!(i68); +lit_macro!(i69); +lit_macro!(i70); +lit_macro!(i71); +lit_macro!(i72); +lit_macro!(i73); +lit_macro!(i74); +lit_macro!(i75); +lit_macro!(i76); +lit_macro!(i77); +lit_macro!(i78); +lit_macro!(i79); +lit_macro!(i80); +lit_macro!(i81); +lit_macro!(i82); +lit_macro!(i83); +lit_macro!(i84); +lit_macro!(i85); +lit_macro!(i86); +lit_macro!(i87); +lit_macro!(i88); +lit_macro!(i89); +lit_macro!(i90); +lit_macro!(i91); +lit_macro!(i92); +lit_macro!(i93); +lit_macro!(i94); +lit_macro!(i95); +lit_macro!(i96); +lit_macro!(i97); +lit_macro!(i98); +lit_macro!(i99); +lit_macro!(i100); +lit_macro!(i101); +lit_macro!(i102); +lit_macro!(i103); +lit_macro!(i104); +lit_macro!(i105); +lit_macro!(i106); +lit_macro!(i107); +lit_macro!(i108); +lit_macro!(i109); +lit_macro!(i110); +lit_macro!(i111); +lit_macro!(i112); +lit_macro!(i113); +lit_macro!(i114); +lit_macro!(i115); +lit_macro!(i116); +lit_macro!(i117); +lit_macro!(i118); +lit_macro!(i119); +lit_macro!(i120); +lit_macro!(i121); +lit_macro!(i122); +lit_macro!(i123); +lit_macro!(i124); +lit_macro!(i125); +lit_macro!(i126); +lit_macro!(i127); diff --git a/src/misc.rs b/src/misc.rs new file mode 100644 index 0000000..c5d67de --- /dev/null +++ b/src/misc.rs @@ -0,0 +1,44 @@ +use crate::sealed::Sealed; +use crate::Aint; + +impl core::fmt::Display for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Display::fmt(&self.0, f) + } +} + +impl core::fmt::Binary for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Binary::fmt(&self.0, f) + } +} + +impl core::fmt::Octal for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Octal::fmt(&self.0, f) + } +} + +impl core::fmt::UpperHex for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::UpperHex::fmt(&self.0, f) + } +} + +impl core::fmt::LowerHex for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::LowerHex::fmt(&self.0, f) + } +} + +impl core::fmt::UpperExp for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::UpperExp::fmt(&self.0, f) + } +} + +impl core::fmt::LowerExp for Aint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::LowerExp::fmt(&self.0, f) + } +} diff --git a/src/non_prim.rs b/src/non_prim.rs new file mode 100644 index 0000000..1e3d926 --- /dev/null +++ b/src/non_prim.rs @@ -0,0 +1,365 @@ +use crate::prim::Prim; +use crate::tybit; +use crate::width; +use crate::Aint; + +pub trait NonPrim: + core::fmt::Debug + + core::fmt::Display + + core::fmt::Octal + + core::fmt::Binary + + core::fmt::UpperHex + + core::fmt::LowerHex + + Clone + + Copy + + PartialEq + + Eq + + PartialOrd + + Ord + + core::hash::Hash + + core::ops::Add + + core::ops::Sub + + core::ops::Mul + + core::ops::Div + + core::ops::Rem + + core::ops::BitAnd + + core::ops::BitOr + + core::ops::BitXor + + core::ops::Not + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::AddAssign + + core::ops::SubAssign + + core::ops::MulAssign + + core::ops::DivAssign + + core::ops::RemAssign + + core::ops::BitAndAssign + + core::ops::BitOrAssign + + core::ops::BitXorAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign +{ + const SIGNED: bool; + const BITS: u32; + const ZERO: Self; + const ONE: Self; + const MIN: Self; + const MAX: Self; + type Signed: tybit::Bit; + type Width: width::Width; +} + +macro_rules! impl_aint { + ($repr:ident, $width:literal) => { + impl NonPrim for Aint<$repr, $width> { + const SIGNED: bool = <$repr as Prim>::SIGNED; + const BITS: u32 = $width; + const ZERO: Self = Self::new_wrapping(0); + const ONE: Self = Self::new_wrapping(1); + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = <$repr as Prim>::Signed; + type Width = width::W<$width>; + } + }; +} + +impl_aint!(u8, 1); +impl_aint!(u8, 2); +impl_aint!(u8, 3); +impl_aint!(u8, 4); +impl_aint!(u8, 5); +impl_aint!(u8, 6); +impl_aint!(u8, 7); + +impl_aint!(u16, 9); +impl_aint!(u16, 10); +impl_aint!(u16, 11); +impl_aint!(u16, 12); +impl_aint!(u16, 13); +impl_aint!(u16, 14); +impl_aint!(u16, 15); + +impl_aint!(u32, 17); +impl_aint!(u32, 18); +impl_aint!(u32, 19); +impl_aint!(u32, 20); +impl_aint!(u32, 21); +impl_aint!(u32, 22); +impl_aint!(u32, 23); +impl_aint!(u32, 24); +impl_aint!(u32, 25); +impl_aint!(u32, 26); +impl_aint!(u32, 27); +impl_aint!(u32, 28); +impl_aint!(u32, 29); +impl_aint!(u32, 30); +impl_aint!(u32, 31); + +impl_aint!(u64, 33); +impl_aint!(u64, 34); +impl_aint!(u64, 35); +impl_aint!(u64, 36); +impl_aint!(u64, 37); +impl_aint!(u64, 38); +impl_aint!(u64, 39); +impl_aint!(u64, 40); +impl_aint!(u64, 41); +impl_aint!(u64, 42); +impl_aint!(u64, 43); +impl_aint!(u64, 44); +impl_aint!(u64, 45); +impl_aint!(u64, 46); +impl_aint!(u64, 47); +impl_aint!(u64, 48); +impl_aint!(u64, 49); +impl_aint!(u64, 50); +impl_aint!(u64, 51); +impl_aint!(u64, 52); +impl_aint!(u64, 53); +impl_aint!(u64, 54); +impl_aint!(u64, 55); +impl_aint!(u64, 56); +impl_aint!(u64, 57); +impl_aint!(u64, 58); +impl_aint!(u64, 59); +impl_aint!(u64, 60); +impl_aint!(u64, 61); +impl_aint!(u64, 62); +impl_aint!(u64, 63); + +impl_aint!(u128, 65); +impl_aint!(u128, 66); +impl_aint!(u128, 67); +impl_aint!(u128, 68); +impl_aint!(u128, 69); +impl_aint!(u128, 70); +impl_aint!(u128, 71); +impl_aint!(u128, 72); +impl_aint!(u128, 73); +impl_aint!(u128, 74); +impl_aint!(u128, 75); +impl_aint!(u128, 76); +impl_aint!(u128, 77); +impl_aint!(u128, 78); +impl_aint!(u128, 79); +impl_aint!(u128, 80); +impl_aint!(u128, 81); +impl_aint!(u128, 82); +impl_aint!(u128, 83); +impl_aint!(u128, 84); +impl_aint!(u128, 85); +impl_aint!(u128, 86); +impl_aint!(u128, 87); +impl_aint!(u128, 88); +impl_aint!(u128, 89); +impl_aint!(u128, 90); +impl_aint!(u128, 91); +impl_aint!(u128, 92); +impl_aint!(u128, 93); +impl_aint!(u128, 94); +impl_aint!(u128, 95); +impl_aint!(u128, 96); +impl_aint!(u128, 97); +impl_aint!(u128, 98); +impl_aint!(u128, 99); +impl_aint!(u128, 100); +impl_aint!(u128, 101); +impl_aint!(u128, 102); +impl_aint!(u128, 103); +impl_aint!(u128, 104); +impl_aint!(u128, 105); +impl_aint!(u128, 106); +impl_aint!(u128, 107); +impl_aint!(u128, 108); +impl_aint!(u128, 109); +impl_aint!(u128, 110); +impl_aint!(u128, 111); +impl_aint!(u128, 112); +impl_aint!(u128, 113); +impl_aint!(u128, 114); +impl_aint!(u128, 115); +impl_aint!(u128, 116); +impl_aint!(u128, 117); +impl_aint!(u128, 118); +impl_aint!(u128, 119); +impl_aint!(u128, 120); +impl_aint!(u128, 121); +impl_aint!(u128, 122); +impl_aint!(u128, 123); +impl_aint!(u128, 124); +impl_aint!(u128, 125); +impl_aint!(u128, 126); +impl_aint!(u128, 127); + +impl_aint!(i8, 1); +impl_aint!(i8, 2); +impl_aint!(i8, 3); +impl_aint!(i8, 4); +impl_aint!(i8, 5); +impl_aint!(i8, 6); +impl_aint!(i8, 7); + +impl_aint!(i16, 9); +impl_aint!(i16, 10); +impl_aint!(i16, 11); +impl_aint!(i16, 12); +impl_aint!(i16, 13); +impl_aint!(i16, 14); +impl_aint!(i16, 15); + +impl_aint!(i32, 17); +impl_aint!(i32, 18); +impl_aint!(i32, 19); +impl_aint!(i32, 20); +impl_aint!(i32, 21); +impl_aint!(i32, 22); +impl_aint!(i32, 23); +impl_aint!(i32, 24); +impl_aint!(i32, 25); +impl_aint!(i32, 26); +impl_aint!(i32, 27); +impl_aint!(i32, 28); +impl_aint!(i32, 29); +impl_aint!(i32, 30); +impl_aint!(i32, 31); + +impl_aint!(i64, 33); +impl_aint!(i64, 34); +impl_aint!(i64, 35); +impl_aint!(i64, 36); +impl_aint!(i64, 37); +impl_aint!(i64, 38); +impl_aint!(i64, 39); +impl_aint!(i64, 40); +impl_aint!(i64, 41); +impl_aint!(i64, 42); +impl_aint!(i64, 43); +impl_aint!(i64, 44); +impl_aint!(i64, 45); +impl_aint!(i64, 46); +impl_aint!(i64, 47); +impl_aint!(i64, 48); +impl_aint!(i64, 49); +impl_aint!(i64, 50); +impl_aint!(i64, 51); +impl_aint!(i64, 52); +impl_aint!(i64, 53); +impl_aint!(i64, 54); +impl_aint!(i64, 55); +impl_aint!(i64, 56); +impl_aint!(i64, 57); +impl_aint!(i64, 58); +impl_aint!(i64, 59); +impl_aint!(i64, 60); +impl_aint!(i64, 61); +impl_aint!(i64, 62); +impl_aint!(i64, 63); + +impl_aint!(i128, 65); +impl_aint!(i128, 66); +impl_aint!(i128, 67); +impl_aint!(i128, 68); +impl_aint!(i128, 69); +impl_aint!(i128, 70); +impl_aint!(i128, 71); +impl_aint!(i128, 72); +impl_aint!(i128, 73); +impl_aint!(i128, 74); +impl_aint!(i128, 75); +impl_aint!(i128, 76); +impl_aint!(i128, 77); +impl_aint!(i128, 78); +impl_aint!(i128, 79); +impl_aint!(i128, 80); +impl_aint!(i128, 81); +impl_aint!(i128, 82); +impl_aint!(i128, 83); +impl_aint!(i128, 84); +impl_aint!(i128, 85); +impl_aint!(i128, 86); +impl_aint!(i128, 87); +impl_aint!(i128, 88); +impl_aint!(i128, 89); +impl_aint!(i128, 90); +impl_aint!(i128, 91); +impl_aint!(i128, 92); +impl_aint!(i128, 93); +impl_aint!(i128, 94); +impl_aint!(i128, 95); +impl_aint!(i128, 96); +impl_aint!(i128, 97); +impl_aint!(i128, 98); +impl_aint!(i128, 99); +impl_aint!(i128, 100); +impl_aint!(i128, 101); +impl_aint!(i128, 102); +impl_aint!(i128, 103); +impl_aint!(i128, 104); +impl_aint!(i128, 105); +impl_aint!(i128, 106); +impl_aint!(i128, 107); +impl_aint!(i128, 108); +impl_aint!(i128, 109); +impl_aint!(i128, 110); +impl_aint!(i128, 111); +impl_aint!(i128, 112); +impl_aint!(i128, 113); +impl_aint!(i128, 114); +impl_aint!(i128, 115); +impl_aint!(i128, 116); +impl_aint!(i128, 117); +impl_aint!(i128, 118); +impl_aint!(i128, 119); +impl_aint!(i128, 120); +impl_aint!(i128, 121); +impl_aint!(i128, 122); +impl_aint!(i128, 123); +impl_aint!(i128, 124); +impl_aint!(i128, 125); +impl_aint!(i128, 126); +impl_aint!(i128, 127); diff --git a/src/num.rs b/src/num.rs new file mode 100644 index 0000000..9569426 --- /dev/null +++ b/src/num.rs @@ -0,0 +1,6355 @@ +use crate::sealed::Sealed; +use crate::Aint; + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 3]; + + fn from_be_bytes(bytes: &[u8; 3]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 3]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 3]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 3]; + + fn to_be_bytes(&self) -> [u8; 3] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 3] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 3] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 5]; + + fn from_be_bytes(bytes: &[u8; 5]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 5]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 5]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 5]; + + fn to_be_bytes(&self) -> [u8; 5] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 5] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 5] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 6]; + + fn from_be_bytes(bytes: &[u8; 6]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 6]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 6]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 6]; + + fn to_be_bytes(&self) -> [u8; 6] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 6] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 6] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 7]; + + fn from_be_bytes(bytes: &[u8; 7]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 7]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 7]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 7]; + + fn to_be_bytes(&self) -> [u8; 7] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 7] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 7] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 9]; + + fn from_be_bytes(bytes: &[u8; 9]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 9]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 9]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 9]; + + fn to_be_bytes(&self) -> [u8; 9] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 9] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 9] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 10]; + + fn from_be_bytes(bytes: &[u8; 10]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 10]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 10]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 10]; + + fn to_be_bytes(&self) -> [u8; 10] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 10] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 10] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 11]; + + fn from_be_bytes(bytes: &[u8; 11]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 11]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 11]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 11]; + + fn to_be_bytes(&self) -> [u8; 11] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 11] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 11] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 12]; + + fn from_be_bytes(bytes: &[u8; 12]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 12]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 12]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 12]; + + fn to_be_bytes(&self) -> [u8; 12] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 12] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 12] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 13]; + + fn from_be_bytes(bytes: &[u8; 13]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 13]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 13]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 13]; + + fn to_be_bytes(&self) -> [u8; 13] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 13] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 13] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 14]; + + fn from_be_bytes(bytes: &[u8; 14]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 14]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 14]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 14]; + + fn to_be_bytes(&self) -> [u8; 14] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 14] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 14] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 15]; + + fn from_be_bytes(bytes: &[u8; 15]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 15]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 15]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 15]; + + fn to_be_bytes(&self) -> [u8; 15] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 15] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 15] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 3]; + + fn from_be_bytes(bytes: &[u8; 3]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 3]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 3]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 3]; + + fn to_be_bytes(&self) -> [u8; 3] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 3] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 3] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 5]; + + fn from_be_bytes(bytes: &[u8; 5]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 5]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 5]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 5]; + + fn to_be_bytes(&self) -> [u8; 5] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 5] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 5] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 6]; + + fn from_be_bytes(bytes: &[u8; 6]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 6]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 6]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 6]; + + fn to_be_bytes(&self) -> [u8; 6] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 6] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 6] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 7]; + + fn from_be_bytes(bytes: &[u8; 7]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 7]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 7]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 7]; + + fn to_be_bytes(&self) -> [u8; 7] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 7] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 7] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 9]; + + fn from_be_bytes(bytes: &[u8; 9]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 9]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 9]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 9]; + + fn to_be_bytes(&self) -> [u8; 9] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 9] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 9] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 10]; + + fn from_be_bytes(bytes: &[u8; 10]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 10]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 10]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 10]; + + fn to_be_bytes(&self) -> [u8; 10] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 10] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 10] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 11]; + + fn from_be_bytes(bytes: &[u8; 11]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 11]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 11]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 11]; + + fn to_be_bytes(&self) -> [u8; 11] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 11] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 11] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 12]; + + fn from_be_bytes(bytes: &[u8; 12]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 12]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 12]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 12]; + + fn to_be_bytes(&self) -> [u8; 12] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 12] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 12] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 13]; + + fn from_be_bytes(bytes: &[u8; 13]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 13]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 13]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 13]; + + fn to_be_bytes(&self) -> [u8; 13] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 13] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 13] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 14]; + + fn from_be_bytes(bytes: &[u8; 14]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 14]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 14]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 14]; + + fn to_be_bytes(&self) -> [u8; 14] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 14] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 14] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::FromBytes for Aint { + type Bytes = [u8; 15]; + + fn from_be_bytes(bytes: &[u8; 15]) -> Self { + >::from_be_bytes(bytes.clone()) + } + + fn from_le_bytes(bytes: &[u8; 15]) -> Self { + >::from_le_bytes(bytes.clone()) + } + + fn from_ne_bytes(bytes: &[u8; 15]) -> Self { + >::from_ne_bytes(bytes.clone()) + } +} + +impl num_traits::ToBytes for Aint { + type Bytes = [u8; 15]; + + fn to_be_bytes(&self) -> [u8; 15] { + >::to_be_bytes(*self) + } + + fn to_le_bytes(&self) -> [u8; 15] { + >::to_le_bytes(*self) + } + + fn to_ne_bytes(&self) -> [u8; 15] { + >::to_ne_bytes(*self) + } +} + +impl num_traits::Zero for Aint { + fn zero() -> Self { + Self(R::ZERO) + } + + fn is_zero(&self) -> bool { + self.0 == R::ZERO + } +} + +impl num_traits::One for Aint { + fn one() -> Self { + Self::_new_wrapping(R::ONE) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_traits::Num for Aint { + type FromStrRadixErr = core::num::ParseIntError; + + fn from_str_radix(s: &str, radix: u32) -> Result { + >::from_str_radix(s, radix) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Integer for Aint { + fn div_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn mod_floor(&self, other: &Self) -> Self { + let val = num_integer::Integer::mod_floor(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd(&self, other: &Self) -> Self { + let val = num_integer::Integer::gcd(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + Self::_new_wrapping(val) + } + + fn lcm(&self, other: &Self) -> Self { + let val = num_integer::Integer::lcm(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + Self::_new_wrapping(val) + } + + fn divides(&self, other: &Self) -> bool { + num_integer::Integer::divides(&self.0, &other.0) + } + + fn is_multiple_of(&self, other: &Self) -> bool { + num_integer::Integer::is_multiple_of(&self.0, &other.0) + } + + fn is_even(&self) -> bool { + num_integer::Integer::is_even(&self.0) + } + + fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + fn div_rem(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_rem(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn div_ceil(&self, other: &Self) -> Self { + let val = num_integer::Integer::div_ceil(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } + + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + let (g, l) = num_integer::Integer::gcd_lcm(&self.0, &other.0); + debug_assert!( + g <= Self::MAX.0 && g >= Self::MIN.0, + "attempt to compute GCD with overflow" + ); + debug_assert!( + l <= Self::MAX.0 && l >= Self::MIN.0, + "attempt to compute LCM with overflow" + ); + (Self::_new_wrapping(g), Self::_new_wrapping(l)) + } + + fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd { + let res = num_integer::Integer::extended_gcd(&self.0, &other.0); + debug_assert!( + (res.gcd <= Self::MAX.0 && res.gcd >= Self::MIN.0) + || (res.x <= Self::MAX.0 && res.x >= Self::MIN.0) + || (res.y <= Self::MAX.0 && res.y >= Self::MIN.0), + "attempt to compute extended GCD with overflow" + ); + num_integer::ExtendedGcd { + gcd: Self::_new_wrapping(res.gcd), + x: Self::_new_wrapping(res.x), + y: Self::_new_wrapping(res.y), + } + } + + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + let (q, r) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + debug_assert!( + q <= Self::MAX.0 && q >= Self::MIN.0, + "attempt to divide with overflow" + ); + debug_assert!( + r <= Self::MAX.0 && r >= Self::MIN.0, + "attempt to compute modulus with overflow" + ); + (Self::_new_wrapping(q), Self::_new_wrapping(r)) + } + + fn next_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::next_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find next multiple with overflow" + ); + Self::_new_wrapping(val) + } + + fn prev_multiple_of(&self, other: &Self) -> Self { + let val = num_integer::Integer::prev_multiple_of(&self.0, &other.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to find previous multiple with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_integer::Roots for Aint { + fn nth_root(&self, n: u32) -> Self { + Self(num_integer::Roots::nth_root(&self.0, n)) + } + + fn sqrt(&self) -> Self { + Self(num_integer::Roots::sqrt(&self.0)) + } + + fn cbrt(&self) -> Self { + Self(num_integer::Roots::cbrt(&self.0)) + } +} + +impl num_traits::Bounded for Aint { + fn min_value() -> Self { + Self::_min() + } + + fn max_value() -> Self { + Self::_max() + } +} + +impl num_traits::FromPrimitive for Aint { + fn from_u8(n: u8) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_u16(n: u16) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_u32(n: u32) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_u64(n: u64) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_u128(n: u128) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_usize(n: usize) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_i8(n: i8) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_i16(n: i16) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_i32(n: i32) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_i64(n: i64) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_i128(n: i128) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } + + fn from_isize(n: isize) -> Option { + match n.try_into() { + Ok(val) => Self::_new(val), + _ => None, + } + } +} + +impl num_traits::ToPrimitive for Aint { + fn to_u8(&self) -> Option { + self.0.try_into().ok() + } + + fn to_u16(&self) -> Option { + self.0.try_into().ok() + } + + fn to_u32(&self) -> Option { + self.0.try_into().ok() + } + + fn to_u64(&self) -> Option { + self.0.try_into().ok() + } + + fn to_u128(&self) -> Option { + self.0.try_into().ok() + } + + fn to_usize(&self) -> Option { + self.0.try_into().ok() + } + + fn to_i8(&self) -> Option { + self.0.try_into().ok() + } + + fn to_i16(&self) -> Option { + self.0.try_into().ok() + } + + fn to_i32(&self) -> Option { + self.0.try_into().ok() + } + + fn to_i64(&self) -> Option { + self.0.try_into().ok() + } + + fn to_i128(&self) -> Option { + self.0.try_into().ok() + } + + fn to_isize(&self) -> Option { + self.0.try_into().ok() + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_u8() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_u16() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_u32() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_u64() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_u128() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_i8() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_i16() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_i32() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_i64() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::NumCast for Aint { + fn from(n: T) -> Option { + match n.to_i128() { + Some(n) => Self::new(n), + None => None, + } + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedNeg for Aint { + fn checked_neg(&self) -> Option { + >::checked_neg(*self) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedAdd for Aint { + fn checked_add(&self, v: &Self) -> Option { + >::checked_add(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedSub for Aint { + fn checked_sub(&self, v: &Self) -> Option { + >::checked_sub(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedMul for Aint { + fn checked_mul(&self, v: &Self) -> Option { + >::checked_mul(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedDiv for Aint { + fn checked_div(&self, v: &Self) -> Option { + >::checked_div(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedRem for Aint { + fn checked_rem(&self, v: &Self) -> Option { + >::checked_rem(*self, *v) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShl for Aint { + fn checked_shl(&self, rhs: u32) -> Option { + >::checked_shl(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::CheckedShr for Aint { + fn checked_shr(&self, rhs: u32) -> Option { + >::checked_shr(*self, rhs) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::Euclid for Aint { + fn div_euclid(&self, v: &Self) -> Self { + >::div_euclid(*self, *v) + } + + fn rem_euclid(&self, v: &Self) -> Self { + >::rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::CheckedEuclid for Aint { + fn checked_div_euclid(&self, v: &Self) -> Option { + >::checked_div_euclid(*self, *v) + } + + fn checked_rem_euclid(&self, v: &Self) -> Option { + >::checked_rem_euclid(*self, *v) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAdd for Aint { + type Output = Self; + + fn mul_add(self, a: Self, b: Self) -> Self { + let val = num_traits::MulAdd::mul_add(self.0, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + Self::new_wrapping(val) + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::MulAddAssign for Aint { + fn mul_add_assign(&mut self, a: Self, b: Self) { + let mut val = self.0; + num_traits::MulAddAssign::mul_add_assign(&mut val, a.0, b.0); + debug_assert!( + val <= Self::MAX.0 && val >= Self::MIN.0, + "attempt to compute fused multiply-add with overflow" + ); + *self = Self::new_wrapping(val); + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::Saturating for Aint { + fn saturating_add(self, v: Self) -> Self { + >::saturating_add(self, v) + } + + fn saturating_sub(self, v: Self) -> Self { + >::saturating_sub(self, v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingAdd for Aint { + fn saturating_add(&self, v: &Self) -> Self { + >::saturating_add(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingSub for Aint { + fn saturating_sub(&self, v: &Self) -> Self { + >::saturating_sub(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::SaturatingMul for Aint { + fn saturating_mul(&self, v: &Self) -> Self { + >::saturating_mul(*self, *v) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingNeg for Aint { + fn wrapping_neg(&self) -> Self { + >::wrapping_neg(*self) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingAdd for Aint { + fn wrapping_add(&self, v: &Self) -> Self { + >::wrapping_add(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingSub for Aint { + fn wrapping_sub(&self, v: &Self) -> Self { + >::wrapping_sub(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingMul for Aint { + fn wrapping_mul(&self, v: &Self) -> Self { + >::wrapping_mul(*self, *v) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShl for Aint { + fn wrapping_shl(&self, rhs: u32) -> Self { + >::wrapping_shl(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl num_traits::WrappingShr for Aint { + fn wrapping_shr(&self, rhs: u32) -> Self { + >::wrapping_shr(*self, rhs) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl + crate::WrappingInto + Copy, const WIDTH: u32> + num_traits::Pow for Aint +{ + type Output = Self; + + fn pow(self, rhs: T) -> Self { + let Ok(exp) = rhs.try_into() else { + debug_assert!(false, "attempt to exponentiate with overflow"); + return Self::wrapping_pow(self, rhs.wrapping_into()); + }; + >::pow(self, exp) + } +} + +impl num_traits::Pow for &Aint +where + Aint: num_traits::Pow, +{ + type Output = as num_traits::Pow>::Output; + + fn pow(self, rhs: T) -> Self::Output { + as num_traits::Pow>::pow(*self, rhs) + } +} + +impl num_traits::Unsigned for Aint {} + +impl num_traits::Unsigned for Aint {} + +impl num_traits::Unsigned for Aint {} + +impl num_traits::Unsigned for Aint {} + +impl num_traits::Unsigned for Aint {} + +impl num_traits::Signed for Aint { + fn abs(&self) -> Self { + >::abs(*self) + } + + fn abs_sub(&self, other: &Self) -> Self { + Self(>::abs_diff(*self, *other).0 as i8) + } + + fn signum(&self) -> Self { + >::signum(*self) + } + + fn is_positive(&self) -> bool { + >::is_positive(*self) + } + + fn is_negative(&self) -> bool { + >::is_negative(*self) + } +} + +impl num_traits::Signed for Aint { + fn abs(&self) -> Self { + >::abs(*self) + } + + fn abs_sub(&self, other: &Self) -> Self { + Self(>::abs_diff(*self, *other).0 as i16) + } + + fn signum(&self) -> Self { + >::signum(*self) + } + + fn is_positive(&self) -> bool { + >::is_positive(*self) + } + + fn is_negative(&self) -> bool { + >::is_negative(*self) + } +} + +impl num_traits::Signed for Aint { + fn abs(&self) -> Self { + >::abs(*self) + } + + fn abs_sub(&self, other: &Self) -> Self { + Self(>::abs_diff(*self, *other).0 as i32) + } + + fn signum(&self) -> Self { + >::signum(*self) + } + + fn is_positive(&self) -> bool { + >::is_positive(*self) + } + + fn is_negative(&self) -> bool { + >::is_negative(*self) + } +} + +impl num_traits::Signed for Aint { + fn abs(&self) -> Self { + >::abs(*self) + } + + fn abs_sub(&self, other: &Self) -> Self { + Self(>::abs_diff(*self, *other).0 as i64) + } + + fn signum(&self) -> Self { + >::signum(*self) + } + + fn is_positive(&self) -> bool { + >::is_positive(*self) + } + + fn is_negative(&self) -> bool { + >::is_negative(*self) + } +} + +impl num_traits::Signed for Aint { + fn abs(&self) -> Self { + >::abs(*self) + } + + fn abs_sub(&self, other: &Self) -> Self { + Self(>::abs_diff(*self, *other).0 as i128) + } + + fn signum(&self) -> Self { + >::signum(*self) + } + + fn is_positive(&self) -> bool { + >::is_positive(*self) + } + + fn is_negative(&self) -> bool { + >::is_negative(*self) + } +} + +impl + num_traits::AsPrimitive> for Aint +where + R1: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.0.as_()) + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> u8 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> u16 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> u32 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> u64 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> u128 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> usize { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> i8 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> i16 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> i32 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> i64 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> i128 { + self.0.as_() + } +} + +impl num_traits::AsPrimitive for Aint +where + R: num_traits::AsPrimitive, +{ + fn as_(self) -> isize { + self.0.as_() + } +} + +impl num_traits::AsPrimitive> for u8 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for u16 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for u32 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for u64 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for u128 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for usize +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for i8 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for i16 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for i32 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for i64 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for i128 +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::AsPrimitive> for isize +where + Self: num_traits::AsPrimitive, +{ + fn as_(self) -> Aint { + >::_new_wrapping(self.as_()) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u32 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u64 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u64 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u64 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + if (self.0 & (1u128 << (Self::BITS - 1))) == 0 { + >::shr(self, n) + } else { + Self((self.0 >> n) | (!(Self::MAX.0 >> n) & Self::MAX.0)) + } + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} + +impl num_traits::PrimInt for Aint { + fn count_ones(self) -> u32 { + >::count_ones(self) + } + + fn count_zeros(self) -> u32 { + >::count_zeros(self) + } + + fn leading_zeros(self) -> u32 { + >::leading_zeros(self) + } + + fn trailing_zeros(self) -> u32 { + >::trailing_zeros(self) + } + + fn leading_ones(self) -> u32 { + >::leading_ones(self) + } + + fn trailing_ones(self) -> u32 { + >::trailing_ones(self) + } + + fn reverse_bits(self) -> Self { + >::reverse_bits(self) + } + + fn rotate_left(self, n: u32) -> Self { + >::rotate_left(self, n) + } + + fn rotate_right(self, n: u32) -> Self { + >::rotate_right(self, n) + } + + fn signed_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn signed_shr(self, n: u32) -> Self { + >::shr(self, n) + } + + fn unsigned_shl(self, n: u32) -> Self { + >::shl(self, n) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self((self.0 >> n) & (Self::MASK >> n)) + } + + fn swap_bytes(self) -> Self { + >::swap_bytes(self) + } + + fn from_be(x: Self) -> Self { + >::from_be(x) + } + + fn from_le(x: Self) -> Self { + >::from_le(x) + } + + fn to_be(self) -> Self { + >::to_be(self) + } + + fn to_le(self) -> Self { + >::to_be(self) + } + + fn pow(self, exp: u32) -> Self { + >::pow(self, exp) + } +} diff --git a/src/ops.rs b/src/ops.rs new file mode 100644 index 0000000..2986d3d --- /dev/null +++ b/src/ops.rs @@ -0,0 +1,412 @@ +use crate::sealed::Sealed; +use crate::Aint; + +impl, const WIDTH: u32> core::ops::Neg for Aint { + type Output = Self; + + fn neg(self) -> Self { + let val = -self.0; + debug_assert!( + val <= Self::_max().0 && val >= Self::_min().0, + "attempt to negate with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl, const WIDTH: u32> core::ops::Neg for &Aint { + type Output = Aint; + + fn neg(self) -> Self::Output { + -*self + } +} + +impl core::ops::Add for Aint { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + let val = self.0 + rhs.0; + debug_assert!( + val <= Self::_max().0 && val >= Self::_min().0, + "attempt to add with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl core::ops::Add<&Aint> for Aint { + type Output = Self; + + fn add(self, rhs: &Aint) -> Self { + self + *rhs + } +} + +impl core::ops::Add> for &Aint { + type Output = Aint; + + fn add(self, rhs: Aint) -> Self::Output { + *self + rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Add<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn add(self, rhs: &'b Aint) -> Self::Output { + *self + *rhs + } +} + +impl core::ops::AddAssign for Aint +where + Self: core::ops::Add, +{ + fn add_assign(&mut self, rhs: T) { + *self = *self + rhs + } +} + +impl core::ops::Sub for Aint { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + let val = self.0 - rhs.0; + debug_assert!( + val <= Self::_max().0 && val >= Self::_min().0, + "attempt to subtract with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl core::ops::Sub<&Aint> for Aint { + type Output = Self; + + fn sub(self, rhs: &Aint) -> Self { + self - *rhs + } +} + +impl core::ops::Sub> for &Aint { + type Output = Aint; + + fn sub(self, rhs: Aint) -> Self::Output { + *self - rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Sub<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn sub(self, rhs: &'b Aint) -> Self::Output { + *self - *rhs + } +} + +impl core::ops::SubAssign for Aint +where + Self: core::ops::Sub, +{ + fn sub_assign(&mut self, rhs: T) { + *self = *self - rhs + } +} + +impl core::ops::Mul for Aint { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + let val = self.0 * rhs.0; + debug_assert!( + val <= Self::_max().0 && val >= Self::_min().0, + "attempt to multiply with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl core::ops::Mul<&Aint> for Aint { + type Output = Self; + + fn mul(self, rhs: &Aint) -> Self { + self * *rhs + } +} + +impl core::ops::Mul> for &Aint { + type Output = Aint; + + fn mul(self, rhs: Aint) -> Self::Output { + *self * rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Mul<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn mul(self, rhs: &'b Aint) -> Self::Output { + *self * *rhs + } +} + +impl core::ops::MulAssign for Aint +where + Self: core::ops::Mul, +{ + fn mul_assign(&mut self, rhs: T) { + *self = *self * rhs + } +} + +impl core::ops::Div for Aint { + type Output = Self; + + fn div(self, rhs: Self) -> Self { + let val = self.0 / rhs.0; + debug_assert!( + val <= Self::_max().0 && val >= Self::_min().0, + "attempt to divide with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl core::ops::Div<&Aint> for Aint { + type Output = Self; + + fn div(self, rhs: &Aint) -> Self { + self / *rhs + } +} + +impl core::ops::Div> for &Aint { + type Output = Aint; + + fn div(self, rhs: Aint) -> Self::Output { + *self / rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Div<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn div(self, rhs: &'b Aint) -> Self::Output { + *self / *rhs + } +} + +impl core::ops::DivAssign for Aint +where + Self: core::ops::Div, +{ + fn div_assign(&mut self, rhs: T) { + *self = *self / rhs + } +} + +impl core::ops::Rem for Aint { + type Output = Self; + + fn rem(self, rhs: Self) -> Self { + let val = self.0 % rhs.0; + debug_assert!( + val <= Self::_max().0 && val >= Self::_min().0, + "attempt to compute modulus with overflow" + ); + Self::_new_wrapping(val) + } +} + +impl core::ops::Rem<&Aint> for Aint { + type Output = Self; + + fn rem(self, rhs: &Aint) -> Self { + self % *rhs + } +} + +impl core::ops::Rem> for &Aint { + type Output = Aint; + + fn rem(self, rhs: Aint) -> Self::Output { + *self % rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Rem<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn rem(self, rhs: &'b Aint) -> Self::Output { + *self % *rhs + } +} + +impl core::ops::RemAssign for Aint +where + Self: core::ops::Rem, +{ + fn rem_assign(&mut self, rhs: T) { + *self = *self % rhs + } +} + +impl core::ops::Not for Aint { + type Output = Self; + + fn not(self) -> Self { + if R::SIGNED { + Self(!self.0) + } else { + Self(!self.0 & Self::_mask()) + } + } +} + +impl core::ops::Not for &Aint { + type Output = Aint; + + fn not(self) -> Self::Output { + !*self + } +} + +impl core::ops::BitAnd for Aint { + type Output = Self; + + fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } +} + +impl core::ops::BitAnd<&Aint> for Aint { + type Output = Self; + + fn bitand(self, rhs: &Aint) -> Self { + self & *rhs + } +} + +impl core::ops::BitAnd> for &Aint { + type Output = Aint; + + fn bitand(self, rhs: Aint) -> Self::Output { + *self & rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::BitAnd<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn bitand(self, rhs: &'b Aint) -> Self::Output { + *self & *rhs + } +} + +impl core::ops::BitAndAssign for Aint +where + Self: core::ops::BitAnd, +{ + fn bitand_assign(&mut self, rhs: T) { + *self = *self & rhs + } +} + +impl core::ops::BitOr for Aint { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } +} + +impl core::ops::BitOr<&Aint> for Aint { + type Output = Self; + + fn bitor(self, rhs: &Aint) -> Self { + self | *rhs + } +} + +impl core::ops::BitOr> for &Aint { + type Output = Aint; + + fn bitor(self, rhs: Aint) -> Self::Output { + *self | rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::BitOr<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn bitor(self, rhs: &'b Aint) -> Self::Output { + *self | *rhs + } +} + +impl core::ops::BitOrAssign for Aint +where + Self: core::ops::BitOr, +{ + fn bitor_assign(&mut self, rhs: T) { + *self = *self | rhs + } +} + +impl core::ops::BitXor for Aint { + type Output = Self; + + fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } +} + +impl core::ops::BitXor<&Aint> for Aint { + type Output = Self; + + fn bitxor(self, rhs: &Aint) -> Self { + self ^ *rhs + } +} + +impl core::ops::BitXor> for &Aint { + type Output = Aint; + + fn bitxor(self, rhs: Aint) -> Self::Output { + *self ^ rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::BitXor<&'b Aint> + for &'a Aint +{ + type Output = Aint; + + fn bitxor(self, rhs: &'b Aint) -> Self::Output { + *self ^ *rhs + } +} + +impl core::ops::BitXorAssign for Aint +where + Self: core::ops::BitXor, +{ + fn bitxor_assign(&mut self, rhs: T) { + *self = *self ^ rhs + } +} diff --git a/src/prim.rs b/src/prim.rs new file mode 100644 index 0000000..5cfd3a3 --- /dev/null +++ b/src/prim.rs @@ -0,0 +1,273 @@ +use crate::tybit; +use crate::width; + +pub trait Prim: + core::fmt::Debug + + core::fmt::Display + + core::fmt::Octal + + core::fmt::Binary + + core::fmt::UpperHex + + core::fmt::LowerHex + + core::fmt::UpperExp + + core::fmt::LowerExp + + Clone + + Copy + + PartialEq + + Eq + + PartialOrd + + Ord + + core::hash::Hash + + core::ops::Add + + core::ops::Sub + + core::ops::Mul + + core::ops::Div + + core::ops::Rem + + core::ops::BitAnd + + core::ops::BitOr + + core::ops::BitXor + + core::ops::Not + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shl + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::Shr + + core::ops::AddAssign + + core::ops::SubAssign + + core::ops::MulAssign + + core::ops::DivAssign + + core::ops::RemAssign + + core::ops::BitAndAssign + + core::ops::BitOrAssign + + core::ops::BitXorAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShlAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::ops::ShrAssign + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryFrom + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + core::convert::TryInto + + Send + + Sync + + Unpin + + 'static +{ + const SIGNED: bool; + const BITS: u32; + const ZERO: Self; + const ONE: Self; + const MIN: Self; + const MAX: Self; + type Signed: tybit::Bit; + type Width: width::Width; +} + +impl Prim for u8 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<8>; +} + +impl Prim for u16 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<16>; +} + +impl Prim for u32 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<32>; +} + +impl Prim for u64 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<64>; +} + +impl Prim for u128 { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + type Width = width::W<128>; +} + +impl Prim for usize { + const SIGNED: bool = false; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_0; + #[cfg(target_pointer_width = "8")] + type Width = width::W<8>; + #[cfg(target_pointer_width = "16")] + type Width = width::W<16>; + #[cfg(target_pointer_width = "32")] + type Width = width::W<32>; + #[cfg(target_pointer_width = "64")] + type Width = width::W<64>; + #[cfg(target_pointer_width = "128")] + type Width = width::W<128>; +} + +impl Prim for i8 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<8>; +} + +impl Prim for i16 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<16>; +} + +impl Prim for i32 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<32>; +} + +impl Prim for i64 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<64>; +} + +impl Prim for i128 { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + type Width = width::W<128>; +} + +impl Prim for isize { + const SIGNED: bool = true; + const BITS: u32 = Self::BITS; + const ZERO: Self = 0; + const ONE: Self = 1; + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + type Signed = tybit::_1; + #[cfg(target_pointer_width = "8")] + type Width = width::W<8>; + #[cfg(target_pointer_width = "16")] + type Width = width::W<16>; + #[cfg(target_pointer_width = "32")] + type Width = width::W<32>; + #[cfg(target_pointer_width = "64")] + type Width = width::W<64>; + #[cfg(target_pointer_width = "128")] + type Width = width::W<128>; +} diff --git a/src/saturating.rs b/src/saturating.rs new file mode 100644 index 0000000..2164519 --- /dev/null +++ b/src/saturating.rs @@ -0,0 +1,1040 @@ +use crate::{prim::Prim, sealed::Sealed, Aint}; + +/// Saturating conversion from one type into another. +/// +/// When the source value is too large to be represented +/// by the destination type, resulting value is saturated +/// to the bounds of the destination type. +/// +/// # Example: +/// ``` +/// # use aint::SaturatingFrom; +/// let value = u8::saturating_from(1000); +/// assert_eq!(value, u8::MAX); +/// ``` +pub trait SaturatingFrom { + fn saturating_from(value: T) -> Self; +} + +/// Saturating conversion from one type into another. +/// +/// When the source value is too large to be represented +/// by the destination type, resulting value is saturated +/// to the bounds of the destination type. +/// +/// # Example: +/// ``` +/// # use aint::SaturatingInto; +/// let value: u8 = 1000.saturating_into(); +/// assert_eq!(value, u8::MAX); +/// ``` +pub trait SaturatingInto { + fn saturating_into(self) -> T; +} + +impl SaturatingInto for F +where + T: SaturatingFrom, +{ + fn saturating_into(self) -> T { + T::saturating_from(self) + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: u8) -> u8 { + value + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: u16) -> u8 { + core::cmp::min(value, u8::MAX as u16) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: u32) -> u8 { + core::cmp::min(value, u8::MAX as u32) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: u64) -> u8 { + core::cmp::min(value, u8::MAX as u64) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: u128) -> u8 { + core::cmp::min(value, u8::MAX as u128) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: usize) -> u8 { + core::cmp::min(value, u8::MAX as usize) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: i8) -> u8 { + core::cmp::max(value, 0) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: i16) -> u8 { + core::cmp::Ord::clamp(value, 0, u8::MAX as i16) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: i32) -> u8 { + core::cmp::Ord::clamp(value, 0, u8::MAX as i32) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: i64) -> u8 { + core::cmp::Ord::clamp(value, 0, u8::MAX as i64) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: i128) -> u8 { + core::cmp::Ord::clamp(value, 0, u8::MAX as i128) as u8 + } +} + +impl SaturatingFrom for u8 { + fn saturating_from(value: isize) -> u8 { + if core::mem::size_of::() > core::mem::size_of::() { + core::cmp::Ord::clamp(value, 0, u8::MAX as isize) as u8 + } else { + core::cmp::max(value, 0) as u8 + } + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: u8) -> u16 { + value as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: u16) -> u16 { + value + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: u32) -> u16 { + core::cmp::min(value, u16::MAX as u32) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: u64) -> u16 { + core::cmp::min(value, u16::MAX as u64) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: u128) -> u16 { + core::cmp::min(value, u16::MAX as u128) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: usize) -> u16 { + core::cmp::min(value, u16::MAX as usize) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: i8) -> u16 { + core::cmp::max(value, 0) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: i16) -> u16 { + core::cmp::max(value, 0) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: i32) -> u16 { + core::cmp::Ord::clamp(value, 0, u16::MAX as i32) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: i64) -> u16 { + core::cmp::Ord::clamp(value, 0, u16::MAX as i64) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: i128) -> u16 { + core::cmp::Ord::clamp(value, 0, u16::MAX as i128) as u16 + } +} + +impl SaturatingFrom for u16 { + fn saturating_from(value: isize) -> u16 { + if core::mem::size_of::() > core::mem::size_of::() { + core::cmp::Ord::clamp(value, 0, u16::MAX as isize) as u16 + } else { + core::cmp::max(value, 0) as u16 + } + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: u8) -> u32 { + value as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: u16) -> u32 { + value as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: u32) -> u32 { + value + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: u64) -> u32 { + core::cmp::min(value, u32::MAX as u64) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: u128) -> u32 { + core::cmp::min(value, u32::MAX as u128) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: usize) -> u32 { + core::cmp::min(value, u32::MAX as usize) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: i8) -> u32 { + core::cmp::max(value, 0) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: i16) -> u32 { + core::cmp::max(value, 0) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: i32) -> u32 { + core::cmp::max(value, 0) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: i64) -> u32 { + core::cmp::Ord::clamp(value, 0, u32::MAX as i64) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: i128) -> u32 { + core::cmp::Ord::clamp(value, 0, u32::MAX as i128) as u32 + } +} + +impl SaturatingFrom for u32 { + fn saturating_from(value: isize) -> u32 { + if core::mem::size_of::() > core::mem::size_of::() { + core::cmp::Ord::clamp(value, 0, u32::MAX as isize) as u32 + } else { + core::cmp::max(value, 0) as u32 + } + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: u8) -> u64 { + value as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: u16) -> u64 { + value as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: u32) -> u64 { + value as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: u64) -> u64 { + value + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: u128) -> u64 { + core::cmp::min(value, u64::MAX as u128) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: usize) -> u64 { + core::cmp::min(value, u64::MAX as usize) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: i8) -> u64 { + core::cmp::max(value, 0) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: i16) -> u64 { + core::cmp::max(value, 0) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: i32) -> u64 { + core::cmp::max(value, 0) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: i64) -> u64 { + core::cmp::max(value, 0) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: i128) -> u64 { + core::cmp::Ord::clamp(value, 0, u64::MAX as i128) as u64 + } +} + +impl SaturatingFrom for u64 { + fn saturating_from(value: isize) -> u64 { + if core::mem::size_of::() > core::mem::size_of::() { + core::cmp::Ord::clamp(value, 0, u64::MAX as isize) as u64 + } else { + core::cmp::max(value, 0) as u64 + } + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: u8) -> u128 { + value as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: u16) -> u128 { + value as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: u32) -> u128 { + value as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: u64) -> u128 { + value as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: u128) -> u128 { + value + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: usize) -> u128 { + core::cmp::min(value, u128::MAX as usize) as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: i8) -> u128 { + core::cmp::max(value, 0) as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: i16) -> u128 { + core::cmp::max(value, 0) as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: i32) -> u128 { + core::cmp::max(value, 0) as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: i64) -> u128 { + core::cmp::max(value, 0) as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: i128) -> u128 { + core::cmp::max(value, 0) as u128 + } +} + +impl SaturatingFrom for u128 { + fn saturating_from(value: isize) -> u128 { + if core::mem::size_of::() > core::mem::size_of::() { + core::cmp::Ord::clamp(value, 0, u128::MAX as isize) as u128 + } else { + core::cmp::max(value, 0) as u128 + } + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: u8) -> usize { + value as usize + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: u16) -> usize { + value as usize + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: u32) -> usize { + value as usize + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: u64) -> usize { + value as usize + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: u128) -> usize { + value as usize + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: usize) -> usize { + value + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: i8) -> usize { + if core::mem::size_of::() <= core::mem::size_of::() { + core::cmp::max(value, 0) as usize + } else { + core::cmp::Ord::clamp(value, 0, usize::MAX as i8) as usize + } + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: i16) -> usize { + if core::mem::size_of::() <= core::mem::size_of::() { + core::cmp::max(value, 0) as usize + } else { + core::cmp::Ord::clamp(value, 0, usize::MAX as i16) as usize + } + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: i32) -> usize { + if core::mem::size_of::() <= core::mem::size_of::() { + core::cmp::max(value, 0) as usize + } else { + core::cmp::Ord::clamp(value, 0, usize::MAX as i32) as usize + } + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: i64) -> usize { + if core::mem::size_of::() <= core::mem::size_of::() { + core::cmp::max(value, 0) as usize + } else { + core::cmp::Ord::clamp(value, 0, usize::MAX as i64) as usize + } + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: i128) -> usize { + if core::mem::size_of::() <= core::mem::size_of::() { + core::cmp::max(value, 0) as usize + } else { + core::cmp::Ord::clamp(value, 0, usize::MAX as i128) as usize + } + } +} + +impl SaturatingFrom for usize { + fn saturating_from(value: isize) -> usize { + core::cmp::max(value, 0) as usize + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: u8) -> i8 { + core::cmp::min(value, i8::MAX as u8) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: u16) -> i8 { + core::cmp::min(value, i8::MAX as u16) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: u32) -> i8 { + core::cmp::min(value, i8::MAX as u32) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: u64) -> i8 { + core::cmp::min(value, i8::MAX as u64) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: u128) -> i8 { + core::cmp::min(value, i8::MAX as u128) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: usize) -> i8 { + core::cmp::min(value, i8::MAX as usize) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: i8) -> i8 { + value + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: i16) -> i8 { + core::cmp::Ord::clamp(value, i8::MIN as i16, i8::MAX as i16) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: i32) -> i8 { + core::cmp::Ord::clamp(value, i8::MIN as i32, i8::MAX as i32) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: i64) -> i8 { + core::cmp::Ord::clamp(value, i8::MIN as i64, i8::MAX as i64) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: i128) -> i8 { + core::cmp::Ord::clamp(value, i8::MIN as i128, i8::MAX as i128) as i8 + } +} + +impl SaturatingFrom for i8 { + fn saturating_from(value: isize) -> i8 { + if core::mem::size_of::() <= core::mem::size_of::() { + value as i8 + } else { + core::cmp::Ord::clamp(value, i8::MIN as isize, i8::MAX as isize) as i8 + } + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: u8) -> i16 { + value as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: u16) -> i16 { + core::cmp::min(value, i16::MAX as u16) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: u32) -> i16 { + core::cmp::min(value, i16::MAX as u32) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: u64) -> i16 { + core::cmp::min(value, i16::MAX as u64) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: u128) -> i16 { + core::cmp::min(value, i16::MAX as u128) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: usize) -> i16 { + if core::mem::size_of::() < core::mem::size_of::() { + value as i16 + } else { + core::cmp::min(value, i16::MAX as usize) as i16 + } + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: i8) -> i16 { + value as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: i16) -> i16 { + value + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: i32) -> i16 { + core::cmp::Ord::clamp(value, i16::MIN as i32, i16::MAX as i32) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: i64) -> i16 { + core::cmp::Ord::clamp(value, i16::MIN as i64, i16::MAX as i64) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: i128) -> i16 { + core::cmp::Ord::clamp(value, i16::MIN as i128, i16::MAX as i128) as i16 + } +} + +impl SaturatingFrom for i16 { + fn saturating_from(value: isize) -> i16 { + if core::mem::size_of::() <= core::mem::size_of::() { + value as i16 + } else { + core::cmp::Ord::clamp(value, i16::MIN as isize, i16::MAX as isize) as i16 + } + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: u8) -> i32 { + value as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: u16) -> i32 { + value as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: u32) -> i32 { + core::cmp::min(value, i32::MAX as u32) as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: u64) -> i32 { + core::cmp::min(value, i32::MAX as u64) as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: u128) -> i32 { + core::cmp::min(value, i32::MAX as u128) as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: usize) -> i32 { + if core::mem::size_of::() < core::mem::size_of::() { + value as i32 + } else { + core::cmp::min(value, i32::MAX as usize) as i32 + } + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: i8) -> i32 { + value as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: i16) -> i32 { + value as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: i32) -> i32 { + value + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: i64) -> i32 { + core::cmp::Ord::clamp(value, i32::MIN as i64, i32::MAX as i64) as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: i128) -> i32 { + core::cmp::Ord::clamp(value, i32::MIN as i128, i32::MAX as i128) as i32 + } +} + +impl SaturatingFrom for i32 { + fn saturating_from(value: isize) -> i32 { + if core::mem::size_of::() <= core::mem::size_of::() { + value as i32 + } else { + core::cmp::Ord::clamp(value, i32::MIN as isize, i32::MAX as isize) as i32 + } + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: u8) -> i64 { + value as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: u16) -> i64 { + value as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: u32) -> i64 { + value as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: u64) -> i64 { + core::cmp::min(value, i64::MAX as u64) as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: u128) -> i64 { + core::cmp::min(value, i64::MAX as u128) as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: usize) -> i64 { + if core::mem::size_of::() < core::mem::size_of::() { + value as i64 + } else { + core::cmp::min(value, i64::MAX as usize) as i64 + } + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: i8) -> i64 { + value as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: i16) -> i64 { + value as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: i32) -> i64 { + value as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: i64) -> i64 { + value + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: i128) -> i64 { + core::cmp::Ord::clamp(value, i64::MIN as i128, i64::MAX as i128) as i64 + } +} + +impl SaturatingFrom for i64 { + fn saturating_from(value: isize) -> i64 { + if core::mem::size_of::() <= core::mem::size_of::() { + value as i64 + } else { + core::cmp::Ord::clamp(value, i64::MIN as isize, i64::MAX as isize) as i64 + } + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: u8) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: u16) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: u32) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: u64) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: u128) -> i128 { + core::cmp::min(value, i128::MAX as u128) as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: usize) -> i128 { + if core::mem::size_of::() < core::mem::size_of::() { + value as i128 + } else { + core::cmp::min(value, i128::MAX as usize) as i128 + } + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: i8) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: i16) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: i32) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: i64) -> i128 { + value as i128 + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: i128) -> i128 { + value + } +} + +impl SaturatingFrom for i128 { + fn saturating_from(value: isize) -> i128 { + if core::mem::size_of::() <= core::mem::size_of::() { + value as i128 + } else { + core::cmp::Ord::clamp(value, i128::MIN as isize, i128::MAX as isize) as i128 + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: u8) -> isize { + if core::mem::size_of::() < core::mem::size_of::() { + value as isize + } else { + core::cmp::min(value, isize::MAX as u8) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: u16) -> isize { + if core::mem::size_of::() < core::mem::size_of::() { + value as isize + } else { + core::cmp::min(value, isize::MAX as u16) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: u32) -> isize { + if core::mem::size_of::() < core::mem::size_of::() { + value as isize + } else { + core::cmp::min(value, isize::MAX as u32) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: u64) -> isize { + if core::mem::size_of::() < core::mem::size_of::() { + value as isize + } else { + core::cmp::min(value, isize::MAX as u64) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: u128) -> isize { + if core::mem::size_of::() < core::mem::size_of::() { + value as isize + } else { + core::cmp::min(value, isize::MAX as u128) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: usize) -> isize { + core::cmp::min(value, isize::MAX as usize) as isize + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: i8) -> isize { + if core::mem::size_of::() <= core::mem::size_of::() { + value as isize + } else { + core::cmp::Ord::clamp(value, isize::MIN as i8, isize::MAX as i8) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: i16) -> isize { + if core::mem::size_of::() <= core::mem::size_of::() { + value as isize + } else { + core::cmp::Ord::clamp(value, isize::MIN as i16, isize::MAX as i16) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: i32) -> isize { + if core::mem::size_of::() <= core::mem::size_of::() { + value as isize + } else { + core::cmp::Ord::clamp(value, isize::MIN as i32, isize::MAX as i32) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: i64) -> isize { + if core::mem::size_of::() <= core::mem::size_of::() { + value as isize + } else { + core::cmp::Ord::clamp(value, isize::MIN as i64, isize::MAX as i64) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: i128) -> isize { + if core::mem::size_of::() <= core::mem::size_of::() { + value as isize + } else { + core::cmp::Ord::clamp(value, isize::MIN as i128, isize::MAX as i128) as isize + } + } +} + +impl SaturatingFrom for isize { + fn saturating_from(value: isize) -> isize { + value + } +} + +impl SaturatingFrom for Aint +where + R: SaturatingFrom, +{ + fn saturating_from(value: F) -> Self { + Self::_new_saturating(value.saturating_into()) + } +} + +impl SaturatingFrom> for T +where + T: SaturatingFrom, +{ + fn saturating_from(value: Aint) -> Self { + value.0.saturating_into() + } +} diff --git a/src/sealed.rs b/src/sealed.rs new file mode 100644 index 0000000..4ebfe0c --- /dev/null +++ b/src/sealed.rs @@ -0,0 +1,21 @@ +pub trait Sealed: crate::prim::Prim {} + +impl Sealed for u8 {} + +impl Sealed for u16 {} + +impl Sealed for u32 {} + +impl Sealed for u64 {} + +impl Sealed for u128 {} + +impl Sealed for i8 {} + +impl Sealed for i16 {} + +impl Sealed for i32 {} + +impl Sealed for i64 {} + +impl Sealed for i128 {} diff --git a/src/serde.rs b/src/serde.rs new file mode 100644 index 0000000..3b05116 --- /dev/null +++ b/src/serde.rs @@ -0,0 +1,301 @@ +use crate::sealed::Sealed; +use crate::Aint; + +#[derive(Clone, Copy)] +struct AintVisitor(core::marker::PhantomData); + +impl<'de, R: Sealed, const WIDTH: u32> serde::de::Visitor<'de> for AintVisitor { + type Value = Aint; + + fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + if R::SIGNED { + write!(f, "a {}-bit signed integer", WIDTH) + } else { + write!(f, "a {}-bit unsigned integer", WIDTH) + } + } + + fn visit_u8(self, v: u8) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Unsigned(v as u64), + &self, + )), + } + } + + fn visit_u16(self, v: u16) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Unsigned(v as u64), + &self, + )), + } + } + + fn visit_u32(self, v: u32) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Unsigned(v as u64), + &self, + )), + } + } + + fn visit_u64(self, v: u64) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value(serde::de::Unexpected::Unsigned(v), &self)), + } + } + + fn visit_u128(self, v: u128) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Unsigned(v as u64), + &self, + )), + } + } + + fn visit_i8(self, v: i8) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Signed(v as i64), + &self, + )), + } + } + + fn visit_i16(self, v: i16) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Signed(v as i64), + &self, + )), + } + } + + fn visit_i32(self, v: i32) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Signed(v as i64), + &self, + )), + } + } + + fn visit_i64(self, v: i64) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value(serde::de::Unexpected::Signed(v), &self)), + } + } + + fn visit_i128(self, v: i128) -> Result { + match v.try_into() { + Ok(val) => Ok(Aint(val)), + _ => Err(E::invalid_value( + serde::de::Unexpected::Signed(v as i64), + &self, + )), + } + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_u8(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_u16(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_u32(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_u64(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_u128(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_i8(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_i16(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_i32(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_i64(visitor) + } +} + +impl<'de, const WIDTH: u32> serde::Deserialize<'de> for Aint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let visitor: AintVisitor = AintVisitor(core::marker::PhantomData); + deserializer.deserialize_i128(visitor) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u8(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u16(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u32(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u64(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u128(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_i8(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_i16(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_i32(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_i64(self.0) + } +} + +impl serde::Serialize for Aint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_i128(self.0) + } +} diff --git a/src/shifts.rs b/src/shifts.rs new file mode 100644 index 0000000..5877182 --- /dev/null +++ b/src/shifts.rs @@ -0,0 +1,2726 @@ +use crate::sealed::Sealed; +use crate::Aint; + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: u8) -> Self { + debug_assert!((rhs as u32) < WIDTH, "attempt to shift left with overflow"); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&u8> for Aint { + type Output = Self; + + fn shl(self, rhs: &u8) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: u8) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b u8> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b u8) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: u8) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&u8> for Aint { + fn shl_assign(&mut self, rhs: &u8) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: u16) -> Self { + debug_assert!((rhs as u32) < WIDTH, "attempt to shift left with overflow"); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&u16> for Aint { + type Output = Self; + + fn shl(self, rhs: &u16) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: u16) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b u16> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b u16) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: u16) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&u16> for Aint { + fn shl_assign(&mut self, rhs: &u16) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: u32) -> Self { + debug_assert!(rhs < WIDTH, "attempt to shift left with overflow"); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&u32> for Aint { + type Output = Self; + + fn shl(self, rhs: &u32) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: u32) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b u32> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b u32) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: u32) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&u32> for Aint { + fn shl_assign(&mut self, rhs: &u32) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: u64) -> Self { + debug_assert!(rhs < WIDTH as u64, "attempt to shift left with overflow"); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&u64> for Aint { + type Output = Self; + + fn shl(self, rhs: &u64) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: u64) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b u64> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b u64) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: u64) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&u64> for Aint { + fn shl_assign(&mut self, rhs: &u64) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: u128) -> Self { + debug_assert!(rhs < WIDTH as u128, "attempt to shift left with overflow"); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&u128> for Aint { + type Output = Self; + + fn shl(self, rhs: &u128) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: u128) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b u128> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b u128) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: u128) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&u128> for Aint { + fn shl_assign(&mut self, rhs: &u128) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: usize) -> Self { + debug_assert!(rhs < WIDTH as usize, "attempt to shift left with overflow"); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&usize> for Aint { + type Output = Self; + + fn shl(self, rhs: &usize) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: usize) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b usize> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b usize) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: usize) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&usize> for Aint { + fn shl_assign(&mut self, rhs: &usize) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: i8) -> Self { + debug_assert!( + (rhs as i64) < (WIDTH as i64) && (rhs as i64) > -(WIDTH as i64), + "attempt to shift left with overflow" + ); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&i8> for Aint { + type Output = Self; + + fn shl(self, rhs: &i8) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: i8) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b i8> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b i8) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: i8) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&i8> for Aint { + fn shl_assign(&mut self, rhs: &i8) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: i16) -> Self { + debug_assert!( + (rhs as i64) < (WIDTH as i64) && (rhs as i64) > -(WIDTH as i64), + "attempt to shift left with overflow" + ); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&i16> for Aint { + type Output = Self; + + fn shl(self, rhs: &i16) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: i16) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b i16> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b i16) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: i16) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&i16> for Aint { + fn shl_assign(&mut self, rhs: &i16) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: i32) -> Self { + debug_assert!( + (rhs as i64) < (WIDTH as i64) && (rhs as i64) > -(WIDTH as i64), + "attempt to shift left with overflow" + ); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&i32> for Aint { + type Output = Self; + + fn shl(self, rhs: &i32) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: i32) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b i32> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b i32) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: i32) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&i32> for Aint { + fn shl_assign(&mut self, rhs: &i32) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: i64) -> Self { + debug_assert!( + rhs < WIDTH as i64 && rhs > -(WIDTH as i64), + "attempt to shift left with overflow" + ); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&i64> for Aint { + type Output = Self; + + fn shl(self, rhs: &i64) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: i64) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b i64> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b i64) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: i64) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&i64> for Aint { + fn shl_assign(&mut self, rhs: &i64) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: i128) -> Self { + debug_assert!( + rhs < WIDTH as i128 && rhs > -(WIDTH as i128), + "attempt to shift left with overflow" + ); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&i128> for Aint { + type Output = Self; + + fn shl(self, rhs: &i128) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: i128) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b i128> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b i128) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: i128) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&i128> for Aint { + fn shl_assign(&mut self, rhs: &i128) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl for Aint { + type Output = Self; + + fn shl(self, rhs: isize) -> Self { + debug_assert!( + rhs < WIDTH as isize && rhs > -(WIDTH as isize), + "attempt to shift left with overflow" + ); + Self::_new_wrapping(self.0 << rhs) + } +} + +impl core::ops::Shl<&isize> for Aint { + type Output = Self; + + fn shl(self, rhs: &isize) -> Self { + self << *rhs + } +} + +impl core::ops::Shl for &Aint { + type Output = Aint; + + fn shl(self, rhs: isize) -> Self::Output { + *self << rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b isize> for &'a Aint { + type Output = Aint; + + fn shl(self, rhs: &'b isize) -> Self::Output { + *self << *rhs + } +} + +impl core::ops::ShlAssign for Aint { + fn shl_assign(&mut self, rhs: isize) { + *self = *self << rhs; + } +} + +impl core::ops::ShlAssign<&isize> for Aint { + fn shl_assign(&mut self, rhs: &isize) { + *self = *self << *rhs; + } +} + +impl core::ops::Shl> + for Aint +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + let rhs: i32 = match rhs.0.try_into() { + Ok(rhs) => rhs, + Err(_) => i32::MAX, + }; + self << rhs + } +} + +impl core::ops::Shl> + for &Aint +{ + type Output = Aint; + + fn shl(self, rhs: Aint) -> Self::Output { + *self << rhs + } +} + +impl core::ops::Shl<&Aint> + for Aint +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << *rhs + } +} + +impl<'a, 'b, R1: Sealed, R2: Sealed, const WIDTH1: u32, const WIDTH2: u32> + core::ops::Shl<&'b Aint> for &'a Aint +{ + type Output = Aint; + + fn shl(self, rhs: &'b Aint) -> Self::Output { + *self << *rhs + } +} + +impl + core::ops::ShlAssign> for Aint +{ + fn shl_assign(&mut self, rhs: Aint) { + *self = *self << rhs; + } +} + +impl + core::ops::ShlAssign<&Aint> for Aint +{ + fn shl_assign(&mut self, rhs: &Aint) { + *self = *self << *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: u8) -> Self { + debug_assert!((rhs as u32) < WIDTH, "attempt to shift right with overflow"); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&u8> for Aint { + type Output = Self; + + fn shr(self, rhs: &u8) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: u8) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b u8> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b u8) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: u8) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&u8> for Aint { + fn shr_assign(&mut self, rhs: &u8) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: u16) -> Self { + debug_assert!((rhs as u32) < WIDTH, "attempt to shift right with overflow"); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&u16> for Aint { + type Output = Self; + + fn shr(self, rhs: &u16) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: u16) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b u16> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b u16) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: u16) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&u16> for Aint { + fn shr_assign(&mut self, rhs: &u16) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: u32) -> Self { + debug_assert!(rhs < WIDTH, "attempt to shift right with overflow"); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&u32> for Aint { + type Output = Self; + + fn shr(self, rhs: &u32) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: u32) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b u32> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b u32) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: u32) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&u32> for Aint { + fn shr_assign(&mut self, rhs: &u32) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: u64) -> Self { + debug_assert!(rhs < WIDTH as u64, "attempt to shift right with overflow"); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&u64> for Aint { + type Output = Self; + + fn shr(self, rhs: &u64) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: u64) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b u64> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b u64) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: u64) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&u64> for Aint { + fn shr_assign(&mut self, rhs: &u64) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: u128) -> Self { + debug_assert!(rhs < WIDTH as u128, "attempt to shift right with overflow"); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&u128> for Aint { + type Output = Self; + + fn shr(self, rhs: &u128) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: u128) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b u128> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b u128) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: u128) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&u128> for Aint { + fn shr_assign(&mut self, rhs: &u128) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: usize) -> Self { + debug_assert!(rhs < WIDTH as usize, "attempt to shift right with overflow"); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&usize> for Aint { + type Output = Self; + + fn shr(self, rhs: &usize) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: usize) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b usize> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b usize) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: usize) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&usize> for Aint { + fn shr_assign(&mut self, rhs: &usize) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: i8) -> Self { + debug_assert!( + (rhs as i64) < (WIDTH as i64) && (rhs as i64) > -(WIDTH as i64), + "attempt to shift right with overflow" + ); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&i8> for Aint { + type Output = Self; + + fn shr(self, rhs: &i8) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: i8) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b i8> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b i8) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: i8) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&i8> for Aint { + fn shr_assign(&mut self, rhs: &i8) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: i16) -> Self { + debug_assert!( + (rhs as i64) < (WIDTH as i64) && (rhs as i64) > -(WIDTH as i64), + "attempt to shift right with overflow" + ); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&i16> for Aint { + type Output = Self; + + fn shr(self, rhs: &i16) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: i16) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b i16> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b i16) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: i16) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&i16> for Aint { + fn shr_assign(&mut self, rhs: &i16) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: i32) -> Self { + debug_assert!( + (rhs as i64) < (WIDTH as i64) && (rhs as i64) > -(WIDTH as i64), + "attempt to shift right with overflow" + ); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&i32> for Aint { + type Output = Self; + + fn shr(self, rhs: &i32) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: i32) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b i32> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b i32) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: i32) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&i32> for Aint { + fn shr_assign(&mut self, rhs: &i32) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: i64) -> Self { + debug_assert!( + rhs < WIDTH as i64 && rhs > -(WIDTH as i64), + "attempt to shift right with overflow" + ); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&i64> for Aint { + type Output = Self; + + fn shr(self, rhs: &i64) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: i64) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b i64> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b i64) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: i64) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&i64> for Aint { + fn shr_assign(&mut self, rhs: &i64) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: i128) -> Self { + debug_assert!( + rhs < WIDTH as i128 && rhs > -(WIDTH as i128), + "attempt to shift right with overflow" + ); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&i128> for Aint { + type Output = Self; + + fn shr(self, rhs: &i128) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: i128) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b i128> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b i128) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: i128) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&i128> for Aint { + fn shr_assign(&mut self, rhs: &i128) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr for Aint { + type Output = Self; + + fn shr(self, rhs: isize) -> Self { + debug_assert!( + rhs < WIDTH as isize && rhs > -(WIDTH as isize), + "attempt to shift right with overflow" + ); + Self::_new_wrapping(self.0 >> rhs) + } +} + +impl core::ops::Shr<&isize> for Aint { + type Output = Self; + + fn shr(self, rhs: &isize) -> Self { + self >> *rhs + } +} + +impl core::ops::Shr for &Aint { + type Output = Aint; + + fn shr(self, rhs: isize) -> Self::Output { + *self >> rhs + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b isize> for &'a Aint { + type Output = Aint; + + fn shr(self, rhs: &'b isize) -> Self::Output { + *self >> *rhs + } +} + +impl core::ops::ShrAssign for Aint { + fn shr_assign(&mut self, rhs: isize) { + *self = *self >> rhs; + } +} + +impl core::ops::ShrAssign<&isize> for Aint { + fn shr_assign(&mut self, rhs: &isize) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shr> + for Aint +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + let rhs: i32 = match rhs.0.try_into() { + Ok(rhs) => rhs, + Err(_) => i32::MAX, + }; + self >> rhs + } +} + +impl core::ops::Shr> + for &Aint +{ + type Output = Aint; + + fn shr(self, rhs: Aint) -> Self::Output { + *self >> rhs + } +} + +impl core::ops::Shr<&Aint> + for Aint +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> *rhs + } +} + +impl<'a, 'b, R1: Sealed, R2: Sealed, const WIDTH1: u32, const WIDTH2: u32> + core::ops::Shr<&'b Aint> for &'a Aint +{ + type Output = Aint; + + fn shr(self, rhs: &'b Aint) -> Self::Output { + *self >> *rhs + } +} + +impl + core::ops::ShrAssign> for Aint +{ + fn shr_assign(&mut self, rhs: Aint) { + *self = *self >> rhs; + } +} + +impl + core::ops::ShrAssign<&Aint> for Aint +{ + fn shr_assign(&mut self, rhs: &Aint) { + *self = *self >> *rhs; + } +} + +impl core::ops::Shl> for u8 +where + u8: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &u8 +where + u8: core::ops::Shl, +{ + type Output = u8; + + fn shl(self, rhs: Aint) -> u8 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for u8 +where + u8: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a u8 +where + u8: core::ops::Shl, +{ + type Output = u8; + + fn shl(self, rhs: &'b Aint) -> u8 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for u8 +where + u8: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for u8 +where + u8: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for u16 +where + u16: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &u16 +where + u16: core::ops::Shl, +{ + type Output = u16; + + fn shl(self, rhs: Aint) -> u16 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for u16 +where + u16: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a u16 +where + u16: core::ops::Shl, +{ + type Output = u16; + + fn shl(self, rhs: &'b Aint) -> u16 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for u16 +where + u16: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for u16 +where + u16: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for u32 +where + u32: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &u32 +where + u32: core::ops::Shl, +{ + type Output = u32; + + fn shl(self, rhs: Aint) -> u32 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for u32 +where + u32: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a u32 +where + u32: core::ops::Shl, +{ + type Output = u32; + + fn shl(self, rhs: &'b Aint) -> u32 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for u32 +where + u32: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for u32 +where + u32: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for u64 +where + u64: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &u64 +where + u64: core::ops::Shl, +{ + type Output = u64; + + fn shl(self, rhs: Aint) -> u64 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for u64 +where + u64: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a u64 +where + u64: core::ops::Shl, +{ + type Output = u64; + + fn shl(self, rhs: &'b Aint) -> u64 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for u64 +where + u64: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for u64 +where + u64: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for u128 +where + u128: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &u128 +where + u128: core::ops::Shl, +{ + type Output = u128; + + fn shl(self, rhs: Aint) -> u128 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for u128 +where + u128: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a u128 +where + u128: core::ops::Shl, +{ + type Output = u128; + + fn shl(self, rhs: &'b Aint) -> u128 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for u128 +where + u128: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for u128 +where + u128: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for usize +where + usize: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &usize +where + usize: core::ops::Shl, +{ + type Output = usize; + + fn shl(self, rhs: Aint) -> usize { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for usize +where + usize: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a usize +where + usize: core::ops::Shl, +{ + type Output = usize; + + fn shl(self, rhs: &'b Aint) -> usize { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for usize +where + usize: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for usize +where + usize: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for i8 +where + i8: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &i8 +where + i8: core::ops::Shl, +{ + type Output = i8; + + fn shl(self, rhs: Aint) -> i8 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for i8 +where + i8: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a i8 +where + i8: core::ops::Shl, +{ + type Output = i8; + + fn shl(self, rhs: &'b Aint) -> i8 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for i8 +where + i8: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for i8 +where + i8: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for i16 +where + i16: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &i16 +where + i16: core::ops::Shl, +{ + type Output = i16; + + fn shl(self, rhs: Aint) -> i16 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for i16 +where + i16: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a i16 +where + i16: core::ops::Shl, +{ + type Output = i16; + + fn shl(self, rhs: &'b Aint) -> i16 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for i16 +where + i16: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for i16 +where + i16: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for i32 +where + i32: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &i32 +where + i32: core::ops::Shl, +{ + type Output = i32; + + fn shl(self, rhs: Aint) -> i32 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for i32 +where + i32: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a i32 +where + i32: core::ops::Shl, +{ + type Output = i32; + + fn shl(self, rhs: &'b Aint) -> i32 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for i32 +where + i32: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for i32 +where + i32: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for i64 +where + i64: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &i64 +where + i64: core::ops::Shl, +{ + type Output = i64; + + fn shl(self, rhs: Aint) -> i64 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for i64 +where + i64: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a i64 +where + i64: core::ops::Shl, +{ + type Output = i64; + + fn shl(self, rhs: &'b Aint) -> i64 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for i64 +where + i64: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for i64 +where + i64: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for i128 +where + i128: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &i128 +where + i128: core::ops::Shl, +{ + type Output = i128; + + fn shl(self, rhs: Aint) -> i128 { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for i128 +where + i128: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a i128 +where + i128: core::ops::Shl, +{ + type Output = i128; + + fn shl(self, rhs: &'b Aint) -> i128 { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for i128 +where + i128: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for i128 +where + i128: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shl> for isize +where + isize: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: Aint) -> Self { + self << rhs.0 + } +} + +impl core::ops::Shl> for &isize +where + isize: core::ops::Shl, +{ + type Output = isize; + + fn shl(self, rhs: Aint) -> isize { + *self << rhs.0 + } +} + +impl core::ops::Shl<&Aint> for isize +where + isize: core::ops::Shl, +{ + type Output = Self; + + fn shl(self, rhs: &Aint) -> Self { + self << rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shl<&'b Aint> for &'a isize +where + isize: core::ops::Shl, +{ + type Output = isize; + + fn shl(self, rhs: &'b Aint) -> isize { + *self << rhs.0 + } +} + +impl core::ops::ShlAssign> for isize +where + isize: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::ShlAssign<&Aint> for isize +where + isize: core::ops::ShlAssign, +{ + fn shl_assign(&mut self, rhs: &Aint) { + self.shl_assign(rhs.0) + } +} + +impl core::ops::Shr> for u8 +where + u8: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &u8 +where + u8: core::ops::Shr, +{ + type Output = u8; + + fn shr(self, rhs: Aint) -> u8 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for u8 +where + u8: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a u8 +where + u8: core::ops::Shr, +{ + type Output = u8; + + fn shr(self, rhs: &'b Aint) -> u8 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for u8 +where + u8: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for u8 +where + u8: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for u16 +where + u16: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &u16 +where + u16: core::ops::Shr, +{ + type Output = u16; + + fn shr(self, rhs: Aint) -> u16 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for u16 +where + u16: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a u16 +where + u16: core::ops::Shr, +{ + type Output = u16; + + fn shr(self, rhs: &'b Aint) -> u16 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for u16 +where + u16: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for u16 +where + u16: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for u32 +where + u32: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &u32 +where + u32: core::ops::Shr, +{ + type Output = u32; + + fn shr(self, rhs: Aint) -> u32 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for u32 +where + u32: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a u32 +where + u32: core::ops::Shr, +{ + type Output = u32; + + fn shr(self, rhs: &'b Aint) -> u32 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for u32 +where + u32: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for u32 +where + u32: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for u64 +where + u64: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &u64 +where + u64: core::ops::Shr, +{ + type Output = u64; + + fn shr(self, rhs: Aint) -> u64 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for u64 +where + u64: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a u64 +where + u64: core::ops::Shr, +{ + type Output = u64; + + fn shr(self, rhs: &'b Aint) -> u64 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for u64 +where + u64: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for u64 +where + u64: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for u128 +where + u128: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &u128 +where + u128: core::ops::Shr, +{ + type Output = u128; + + fn shr(self, rhs: Aint) -> u128 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for u128 +where + u128: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a u128 +where + u128: core::ops::Shr, +{ + type Output = u128; + + fn shr(self, rhs: &'b Aint) -> u128 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for u128 +where + u128: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for u128 +where + u128: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for usize +where + usize: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &usize +where + usize: core::ops::Shr, +{ + type Output = usize; + + fn shr(self, rhs: Aint) -> usize { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for usize +where + usize: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a usize +where + usize: core::ops::Shr, +{ + type Output = usize; + + fn shr(self, rhs: &'b Aint) -> usize { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for usize +where + usize: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for usize +where + usize: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for i8 +where + i8: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &i8 +where + i8: core::ops::Shr, +{ + type Output = i8; + + fn shr(self, rhs: Aint) -> i8 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for i8 +where + i8: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a i8 +where + i8: core::ops::Shr, +{ + type Output = i8; + + fn shr(self, rhs: &'b Aint) -> i8 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for i8 +where + i8: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for i8 +where + i8: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for i16 +where + i16: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &i16 +where + i16: core::ops::Shr, +{ + type Output = i16; + + fn shr(self, rhs: Aint) -> i16 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for i16 +where + i16: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a i16 +where + i16: core::ops::Shr, +{ + type Output = i16; + + fn shr(self, rhs: &'b Aint) -> i16 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for i16 +where + i16: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for i16 +where + i16: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for i32 +where + i32: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &i32 +where + i32: core::ops::Shr, +{ + type Output = i32; + + fn shr(self, rhs: Aint) -> i32 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for i32 +where + i32: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a i32 +where + i32: core::ops::Shr, +{ + type Output = i32; + + fn shr(self, rhs: &'b Aint) -> i32 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for i32 +where + i32: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for i32 +where + i32: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for i64 +where + i64: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &i64 +where + i64: core::ops::Shr, +{ + type Output = i64; + + fn shr(self, rhs: Aint) -> i64 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for i64 +where + i64: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a i64 +where + i64: core::ops::Shr, +{ + type Output = i64; + + fn shr(self, rhs: &'b Aint) -> i64 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for i64 +where + i64: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for i64 +where + i64: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for i128 +where + i128: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &i128 +where + i128: core::ops::Shr, +{ + type Output = i128; + + fn shr(self, rhs: Aint) -> i128 { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for i128 +where + i128: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a i128 +where + i128: core::ops::Shr, +{ + type Output = i128; + + fn shr(self, rhs: &'b Aint) -> i128 { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for i128 +where + i128: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for i128 +where + i128: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::Shr> for isize +where + isize: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: Aint) -> Self { + self >> rhs.0 + } +} + +impl core::ops::Shr> for &isize +where + isize: core::ops::Shr, +{ + type Output = isize; + + fn shr(self, rhs: Aint) -> isize { + *self >> rhs.0 + } +} + +impl core::ops::Shr<&Aint> for isize +where + isize: core::ops::Shr, +{ + type Output = Self; + + fn shr(self, rhs: &Aint) -> Self { + self >> rhs.0 + } +} + +impl<'a, 'b, R: Sealed, const WIDTH: u32> core::ops::Shr<&'b Aint> for &'a isize +where + isize: core::ops::Shr, +{ + type Output = isize; + + fn shr(self, rhs: &'b Aint) -> isize { + *self >> rhs.0 + } +} + +impl core::ops::ShrAssign> for isize +where + isize: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: Aint) { + self.shr_assign(rhs.0) + } +} + +impl core::ops::ShrAssign<&Aint> for isize +where + isize: core::ops::ShrAssign, +{ + fn shr_assign(&mut self, rhs: &Aint) { + self.shr_assign(rhs.0) + } +} diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..2aa500c --- /dev/null +++ b/src/test.rs @@ -0,0 +1,538 @@ +use crate::*; +use paste::paste; + +macro_rules! auto_test { + ($int:ident, $bits:literal, $min:literal, $max:literal) => { + paste! { + #[test] + fn [<$int _consts>]() { + let bits = $bits; + let min = $min; + let max = $max; + + assert_eq!($int::BITS, bits); + assert_eq!($int::MIN.repr(), min); + assert_eq!($int::MAX.repr(), max); + assert_eq!($int::MIN, $int!($min)); + assert_eq!($int::MAX, $int!($max)); + } + + #[test] + fn [<$int _new>]() { + let min = $min; + let max = $max; + + assert_eq!($int::new(min), Some($int!($min))); + assert_eq!($int::new(max), Some($int!($max))); + assert_eq!($int::new(max + 1), None); + assert_eq!($int::new(min.wrapping_sub(1)), None); + } + + #[test] + fn [<$int _new_wrapping>]() { + let min = $min; + let max = $max; + + assert_eq!($int::new_wrapping(min), $int!($min)); + assert_eq!($int::new_wrapping(max), $int!($max)); + assert_eq!($int::new_wrapping(max + 1), $int!($min)); + assert_eq!($int::new_wrapping(min.wrapping_sub(1)), $int!($max)); + } + + #[test] + fn [<$int _new_saturating>]() { + let min = $min; + let max = $max; + + assert_eq!($int::new_saturating(min), $int!($min)); + assert_eq!($int::new_saturating(max), $int!($max)); + assert_eq!($int::new_saturating(max + 1), $int!($max)); + if min != 0 { + assert_eq!($int::new_saturating(min - 1), $int!($min)); + } + } + } + }; +} + +auto_test!(u1, 1, 0, 1); +auto_test!(u2, 2, 0, 3); +auto_test!(u3, 3, 0, 7); +auto_test!(u4, 4, 0, 15); +auto_test!(u5, 5, 0, 31); +auto_test!(u6, 6, 0, 63); +auto_test!(u7, 7, 0, 127); +auto_test!(u9, 9, 0, 511); +auto_test!(u10, 10, 0, 1023); +auto_test!(u11, 11, 0, 2047); +auto_test!(u12, 12, 0, 4095); +auto_test!(u13, 13, 0, 8191); +auto_test!(u14, 14, 0, 16383); +auto_test!(u15, 15, 0, 32767); +auto_test!(u17, 17, 0, 131071); +auto_test!(u18, 18, 0, 262143); +auto_test!(u19, 19, 0, 524287); +auto_test!(u20, 20, 0, 1048575); +auto_test!(u21, 21, 0, 2097151); +auto_test!(u22, 22, 0, 4194303); +auto_test!(u23, 23, 0, 8388607); +auto_test!(u24, 24, 0, 16777215); +auto_test!(u25, 25, 0, 33554431); +auto_test!(u26, 26, 0, 67108863); +auto_test!(u27, 27, 0, 134217727); +auto_test!(u28, 28, 0, 268435455); +auto_test!(u29, 29, 0, 536870911); +auto_test!(u30, 30, 0, 1073741823); +auto_test!(u31, 31, 0, 2147483647); +auto_test!(u33, 33, 0, 8589934591); +auto_test!(u34, 34, 0, 17179869183); +auto_test!(u35, 35, 0, 34359738367); +auto_test!(u36, 36, 0, 68719476735); +auto_test!(u37, 37, 0, 137438953471); +auto_test!(u38, 38, 0, 274877906943); +auto_test!(u39, 39, 0, 549755813887); +auto_test!(u40, 40, 0, 1099511627775); +auto_test!(u41, 41, 0, 2199023255551); +auto_test!(u42, 42, 0, 4398046511103); +auto_test!(u43, 43, 0, 8796093022207); +auto_test!(u44, 44, 0, 17592186044415); +auto_test!(u45, 45, 0, 35184372088831); +auto_test!(u46, 46, 0, 70368744177663); +auto_test!(u47, 47, 0, 140737488355327); +auto_test!(u48, 48, 0, 281474976710655); +auto_test!(u49, 49, 0, 562949953421311); +auto_test!(u50, 50, 0, 1125899906842623); +auto_test!(u51, 51, 0, 2251799813685247); +auto_test!(u52, 52, 0, 4503599627370495); +auto_test!(u53, 53, 0, 9007199254740991); +auto_test!(u54, 54, 0, 18014398509481983); +auto_test!(u55, 55, 0, 36028797018963967); +auto_test!(u56, 56, 0, 72057594037927935); +auto_test!(u57, 57, 0, 144115188075855871); +auto_test!(u58, 58, 0, 288230376151711743); +auto_test!(u59, 59, 0, 576460752303423487); +auto_test!(u60, 60, 0, 1152921504606846975); +auto_test!(u61, 61, 0, 2305843009213693951); +auto_test!(u62, 62, 0, 4611686018427387903); +auto_test!(u63, 63, 0, 9223372036854775807); +auto_test!(u65, 65, 0, 36893488147419103231); +auto_test!(u66, 66, 0, 73786976294838206463); +auto_test!(u67, 67, 0, 147573952589676412927); +auto_test!(u68, 68, 0, 295147905179352825855); +auto_test!(u69, 69, 0, 590295810358705651711); +auto_test!(u70, 70, 0, 1180591620717411303423); +auto_test!(u71, 71, 0, 2361183241434822606847); +auto_test!(u72, 72, 0, 4722366482869645213695); +auto_test!(u73, 73, 0, 9444732965739290427391); +auto_test!(u74, 74, 0, 18889465931478580854783); +auto_test!(u75, 75, 0, 37778931862957161709567); +auto_test!(u76, 76, 0, 75557863725914323419135); +auto_test!(u77, 77, 0, 151115727451828646838271); +auto_test!(u78, 78, 0, 302231454903657293676543); +auto_test!(u79, 79, 0, 604462909807314587353087); +auto_test!(u80, 80, 0, 1208925819614629174706175); +auto_test!(u81, 81, 0, 2417851639229258349412351); +auto_test!(u82, 82, 0, 4835703278458516698824703); +auto_test!(u83, 83, 0, 9671406556917033397649407); +auto_test!(u84, 84, 0, 19342813113834066795298815); +auto_test!(u85, 85, 0, 38685626227668133590597631); +auto_test!(u86, 86, 0, 77371252455336267181195263); +auto_test!(u87, 87, 0, 154742504910672534362390527); +auto_test!(u88, 88, 0, 309485009821345068724781055); +auto_test!(u89, 89, 0, 618970019642690137449562111); +auto_test!(u90, 90, 0, 1237940039285380274899124223); +auto_test!(u91, 91, 0, 2475880078570760549798248447); +auto_test!(u92, 92, 0, 4951760157141521099596496895); +auto_test!(u93, 93, 0, 9903520314283042199192993791); +auto_test!(u94, 94, 0, 19807040628566084398385987583); +auto_test!(u95, 95, 0, 39614081257132168796771975167); +auto_test!(u96, 96, 0, 79228162514264337593543950335); +auto_test!(u97, 97, 0, 158456325028528675187087900671); +auto_test!(u98, 98, 0, 316912650057057350374175801343); +auto_test!(u99, 99, 0, 633825300114114700748351602687); +auto_test!(u100, 100, 0, 1267650600228229401496703205375); +auto_test!(u101, 101, 0, 2535301200456458802993406410751); +auto_test!(u102, 102, 0, 5070602400912917605986812821503); +auto_test!(u103, 103, 0, 10141204801825835211973625643007); +auto_test!(u104, 104, 0, 20282409603651670423947251286015); +auto_test!(u105, 105, 0, 40564819207303340847894502572031); +auto_test!(u106, 106, 0, 81129638414606681695789005144063); +auto_test!(u107, 107, 0, 162259276829213363391578010288127); +auto_test!(u108, 108, 0, 324518553658426726783156020576255); +auto_test!(u109, 109, 0, 649037107316853453566312041152511); +auto_test!(u110, 110, 0, 1298074214633706907132624082305023); +auto_test!(u111, 111, 0, 2596148429267413814265248164610047); +auto_test!(u112, 112, 0, 5192296858534827628530496329220095); +auto_test!(u113, 113, 0, 10384593717069655257060992658440191); +auto_test!(u114, 114, 0, 20769187434139310514121985316880383); +auto_test!(u115, 115, 0, 41538374868278621028243970633760767); +auto_test!(u116, 116, 0, 83076749736557242056487941267521535); +auto_test!(u117, 117, 0, 166153499473114484112975882535043071); +auto_test!(u118, 118, 0, 332306998946228968225951765070086143); +auto_test!(u119, 119, 0, 664613997892457936451903530140172287); +auto_test!(u120, 120, 0, 1329227995784915872903807060280344575); +auto_test!(u121, 121, 0, 2658455991569831745807614120560689151); +auto_test!(u122, 122, 0, 5316911983139663491615228241121378303); +auto_test!(u123, 123, 0, 10633823966279326983230456482242756607); +auto_test!(u124, 124, 0, 21267647932558653966460912964485513215); +auto_test!(u125, 125, 0, 42535295865117307932921825928971026431); +auto_test!(u126, 126, 0, 85070591730234615865843651857942052863); +auto_test!(u127, 127, 0, 170141183460469231731687303715884105727); +auto_test!(i1, 1, -1, 0); +auto_test!(i2, 2, -2, 1); +auto_test!(i3, 3, -4, 3); +auto_test!(i4, 4, -8, 7); +auto_test!(i5, 5, -16, 15); +auto_test!(i6, 6, -32, 31); +auto_test!(i7, 7, -64, 63); +auto_test!(i9, 9, -256, 255); +auto_test!(i10, 10, -512, 511); +auto_test!(i11, 11, -1024, 1023); +auto_test!(i12, 12, -2048, 2047); +auto_test!(i13, 13, -4096, 4095); +auto_test!(i14, 14, -8192, 8191); +auto_test!(i15, 15, -16384, 16383); +auto_test!(i17, 17, -65536, 65535); +auto_test!(i18, 18, -131072, 131071); +auto_test!(i19, 19, -262144, 262143); +auto_test!(i20, 20, -524288, 524287); +auto_test!(i21, 21, -1048576, 1048575); +auto_test!(i22, 22, -2097152, 2097151); +auto_test!(i23, 23, -4194304, 4194303); +auto_test!(i24, 24, -8388608, 8388607); +auto_test!(i25, 25, -16777216, 16777215); +auto_test!(i26, 26, -33554432, 33554431); +auto_test!(i27, 27, -67108864, 67108863); +auto_test!(i28, 28, -134217728, 134217727); +auto_test!(i29, 29, -268435456, 268435455); +auto_test!(i30, 30, -536870912, 536870911); +auto_test!(i31, 31, -1073741824, 1073741823); +auto_test!(i33, 33, -4294967296, 4294967295); +auto_test!(i34, 34, -8589934592, 8589934591); +auto_test!(i35, 35, -17179869184, 17179869183); +auto_test!(i36, 36, -34359738368, 34359738367); +auto_test!(i37, 37, -68719476736, 68719476735); +auto_test!(i38, 38, -137438953472, 137438953471); +auto_test!(i39, 39, -274877906944, 274877906943); +auto_test!(i40, 40, -549755813888, 549755813887); +auto_test!(i41, 41, -1099511627776, 1099511627775); +auto_test!(i42, 42, -2199023255552, 2199023255551); +auto_test!(i43, 43, -4398046511104, 4398046511103); +auto_test!(i44, 44, -8796093022208, 8796093022207); +auto_test!(i45, 45, -17592186044416, 17592186044415); +auto_test!(i46, 46, -35184372088832, 35184372088831); +auto_test!(i47, 47, -70368744177664, 70368744177663); +auto_test!(i48, 48, -140737488355328, 140737488355327); +auto_test!(i49, 49, -281474976710656, 281474976710655); +auto_test!(i50, 50, -562949953421312, 562949953421311); +auto_test!(i51, 51, -1125899906842624, 1125899906842623); +auto_test!(i52, 52, -2251799813685248, 2251799813685247); +auto_test!(i53, 53, -4503599627370496, 4503599627370495); +auto_test!(i54, 54, -9007199254740992, 9007199254740991); +auto_test!(i55, 55, -18014398509481984, 18014398509481983); +auto_test!(i56, 56, -36028797018963968, 36028797018963967); +auto_test!(i57, 57, -72057594037927936, 72057594037927935); +auto_test!(i58, 58, -144115188075855872, 144115188075855871); +auto_test!(i59, 59, -288230376151711744, 288230376151711743); +auto_test!(i60, 60, -576460752303423488, 576460752303423487); +auto_test!(i61, 61, -1152921504606846976, 1152921504606846975); +auto_test!(i62, 62, -2305843009213693952, 2305843009213693951); +auto_test!(i63, 63, -4611686018427387904, 4611686018427387903); +auto_test!(i65, 65, -18446744073709551616, 18446744073709551615); +auto_test!(i66, 66, -36893488147419103232, 36893488147419103231); +auto_test!(i67, 67, -73786976294838206464, 73786976294838206463); +auto_test!(i68, 68, -147573952589676412928, 147573952589676412927); +auto_test!(i69, 69, -295147905179352825856, 295147905179352825855); +auto_test!(i70, 70, -590295810358705651712, 590295810358705651711); +auto_test!(i71, 71, -1180591620717411303424, 1180591620717411303423); +auto_test!(i72, 72, -2361183241434822606848, 2361183241434822606847); +auto_test!(i73, 73, -4722366482869645213696, 4722366482869645213695); +auto_test!(i74, 74, -9444732965739290427392, 9444732965739290427391); +auto_test!(i75, 75, -18889465931478580854784, 18889465931478580854783); +auto_test!(i76, 76, -37778931862957161709568, 37778931862957161709567); +auto_test!(i77, 77, -75557863725914323419136, 75557863725914323419135); +auto_test!(i78, 78, -151115727451828646838272, 151115727451828646838271); +auto_test!(i79, 79, -302231454903657293676544, 302231454903657293676543); +auto_test!(i80, 80, -604462909807314587353088, 604462909807314587353087); +auto_test!( + i81, + 81, + -1208925819614629174706176, + 1208925819614629174706175 +); +auto_test!( + i82, + 82, + -2417851639229258349412352, + 2417851639229258349412351 +); +auto_test!( + i83, + 83, + -4835703278458516698824704, + 4835703278458516698824703 +); +auto_test!( + i84, + 84, + -9671406556917033397649408, + 9671406556917033397649407 +); +auto_test!( + i85, + 85, + -19342813113834066795298816, + 19342813113834066795298815 +); +auto_test!( + i86, + 86, + -38685626227668133590597632, + 38685626227668133590597631 +); +auto_test!( + i87, + 87, + -77371252455336267181195264, + 77371252455336267181195263 +); +auto_test!( + i88, + 88, + -154742504910672534362390528, + 154742504910672534362390527 +); +auto_test!( + i89, + 89, + -309485009821345068724781056, + 309485009821345068724781055 +); +auto_test!( + i90, + 90, + -618970019642690137449562112, + 618970019642690137449562111 +); +auto_test!( + i91, + 91, + -1237940039285380274899124224, + 1237940039285380274899124223 +); +auto_test!( + i92, + 92, + -2475880078570760549798248448, + 2475880078570760549798248447 +); +auto_test!( + i93, + 93, + -4951760157141521099596496896, + 4951760157141521099596496895 +); +auto_test!( + i94, + 94, + -9903520314283042199192993792, + 9903520314283042199192993791 +); +auto_test!( + i95, + 95, + -19807040628566084398385987584, + 19807040628566084398385987583 +); +auto_test!( + i96, + 96, + -39614081257132168796771975168, + 39614081257132168796771975167 +); +auto_test!( + i97, + 97, + -79228162514264337593543950336, + 79228162514264337593543950335 +); +auto_test!( + i98, + 98, + -158456325028528675187087900672, + 158456325028528675187087900671 +); +auto_test!( + i99, + 99, + -316912650057057350374175801344, + 316912650057057350374175801343 +); +auto_test!( + i100, + 100, + -633825300114114700748351602688, + 633825300114114700748351602687 +); +auto_test!( + i101, + 101, + -1267650600228229401496703205376, + 1267650600228229401496703205375 +); +auto_test!( + i102, + 102, + -2535301200456458802993406410752, + 2535301200456458802993406410751 +); +auto_test!( + i103, + 103, + -5070602400912917605986812821504, + 5070602400912917605986812821503 +); +auto_test!( + i104, + 104, + -10141204801825835211973625643008, + 10141204801825835211973625643007 +); +auto_test!( + i105, + 105, + -20282409603651670423947251286016, + 20282409603651670423947251286015 +); +auto_test!( + i106, + 106, + -40564819207303340847894502572032, + 40564819207303340847894502572031 +); +auto_test!( + i107, + 107, + -81129638414606681695789005144064, + 81129638414606681695789005144063 +); +auto_test!( + i108, + 108, + -162259276829213363391578010288128, + 162259276829213363391578010288127 +); +auto_test!( + i109, + 109, + -324518553658426726783156020576256, + 324518553658426726783156020576255 +); +auto_test!( + i110, + 110, + -649037107316853453566312041152512, + 649037107316853453566312041152511 +); +auto_test!( + i111, + 111, + -1298074214633706907132624082305024, + 1298074214633706907132624082305023 +); +auto_test!( + i112, + 112, + -2596148429267413814265248164610048, + 2596148429267413814265248164610047 +); +auto_test!( + i113, + 113, + -5192296858534827628530496329220096, + 5192296858534827628530496329220095 +); +auto_test!( + i114, + 114, + -10384593717069655257060992658440192, + 10384593717069655257060992658440191 +); +auto_test!( + i115, + 115, + -20769187434139310514121985316880384, + 20769187434139310514121985316880383 +); +auto_test!( + i116, + 116, + -41538374868278621028243970633760768, + 41538374868278621028243970633760767 +); +auto_test!( + i117, + 117, + -83076749736557242056487941267521536, + 83076749736557242056487941267521535 +); +auto_test!( + i118, + 118, + -166153499473114484112975882535043072, + 166153499473114484112975882535043071 +); +auto_test!( + i119, + 119, + -332306998946228968225951765070086144, + 332306998946228968225951765070086143 +); +auto_test!( + i120, + 120, + -664613997892457936451903530140172288, + 664613997892457936451903530140172287 +); +auto_test!( + i121, + 121, + -1329227995784915872903807060280344576, + 1329227995784915872903807060280344575 +); +auto_test!( + i122, + 122, + -2658455991569831745807614120560689152, + 2658455991569831745807614120560689151 +); +auto_test!( + i123, + 123, + -5316911983139663491615228241121378304, + 5316911983139663491615228241121378303 +); +auto_test!( + i124, + 124, + -10633823966279326983230456482242756608, + 10633823966279326983230456482242756607 +); +auto_test!( + i125, + 125, + -21267647932558653966460912964485513216, + 21267647932558653966460912964485513215 +); +auto_test!( + i126, + 126, + -42535295865117307932921825928971026432, + 42535295865117307932921825928971026431 +); +auto_test!( + i127, + 127, + -85070591730234615865843651857942052864, + 85070591730234615865843651857942052863 +); diff --git a/src/tybit.rs b/src/tybit.rs new file mode 100644 index 0000000..acbc0cc --- /dev/null +++ b/src/tybit.rs @@ -0,0 +1,194 @@ +pub enum _0 {} +pub enum _1 {} + +pub trait Bit { + const VALUE: u32; + type Not: Bit; + type And: Bit; + type Or: Bit; + type Xor: Bit; + type Eq: Bit; + type Ne: Bit; + type Lt: Bit; + type Gt: Bit; + type Le: Bit; + type Ge: Bit; + type Add: Bit; + type AddCarry: Bit; +} + +pub trait Assert: Bit {} + +impl Bit for _0 { + const VALUE: u32 = 0; + type Not = _1; + type And = <_0 as ops::And>::Res; + type Or = <_0 as ops::Or>::Res; + type Xor = <_0 as ops::Xor>::Res; + type Eq = <_0 as ops::Eq>::Res; + type Ne = <_0 as ops::Ne>::Res; + type Lt = <_0 as ops::Lt>::Res; + type Gt = <_0 as ops::Gt>::Res; + type Le = <_0 as ops::Le>::Res; + type Ge = <_0 as ops::Ge>::Res; + type Add = <_0 as ops::Add>::Res; + type AddCarry = <_0 as ops::Add>::Carry; +} + +impl Bit for _1 { + const VALUE: u32 = 1; + type Not = _0; + type And = <_1 as ops::And>::Res; + type Or = <_1 as ops::Or>::Res; + type Xor = <_1 as ops::Xor>::Res; + type Eq = <_1 as ops::Eq>::Res; + type Ne = <_1 as ops::Ne>::Res; + type Lt = <_1 as ops::Lt>::Res; + type Gt = <_1 as ops::Gt>::Res; + type Le = <_1 as ops::Le>::Res; + type Ge = <_1 as ops::Ge>::Res; + type Add = <_1 as ops::Add>::Res; + type AddCarry = <_1 as ops::Add>::Carry; +} + +impl Assert for _1 {} + +pub type Not = ::Not; +pub type And = ::And; +pub type Or = ::Or; +//pub type Xor = ::Xor; +pub type Eq = ::Eq; +//pub type Ne = ::Ne; +pub type Lt = ::Lt; +//pub type Gt = ::Gt; +//pub type Le = ::Le; +//pub type Ge = ::Ge; +pub type Add = ::Add; +pub type AddCarry = ::AddCarry; + +mod ops { + use super::{Bit, _0, _1}; + + pub trait And: Bit { + type Res: Bit; + } + + pub trait Or: Bit { + type Res: Bit; + } + + pub trait Xor: Bit { + type Res: Bit; + } + + pub trait Eq: Bit { + type Res: Bit; + } + + pub trait Ne: Bit { + type Res: Bit; + } + + pub trait Lt: Bit { + type Res: Bit; + } + + pub trait Gt: Bit { + type Res: Bit; + } + + pub trait Le: Bit { + type Res: Bit; + } + + pub trait Ge: Bit { + type Res: Bit; + } + + pub trait Add: Bit { + type Res: Bit; + type Carry: Bit; + } + + impl And for _0 { + type Res = _0; + } + + impl And for _1 { + type Res = Rhs; + } + + impl Or for _0 { + type Res = Rhs; + } + + impl Or for _1 { + type Res = _1; + } + + impl Xor for _0 { + type Res = Rhs; + } + + impl Xor for _1 { + type Res = Rhs::Not; + } + + impl Eq for _0 { + type Res = Rhs::Not; + } + + impl Eq for _1 { + type Res = Rhs; + } + + impl Ne for _0 { + type Res = Rhs; + } + + impl Ne for _1 { + type Res = Rhs::Not; + } + + impl Lt for _0 { + type Res = Rhs; + } + + impl Lt for _1 { + type Res = _0; + } + + impl Gt for _0 { + type Res = _0; + } + + impl Gt for _1 { + type Res = Rhs::Not; + } + + impl Le for _0 { + type Res = _1; + } + + impl Le for _1 { + type Res = Rhs; + } + + impl Ge for _0 { + type Res = Rhs::Not; + } + + impl Ge for _1 { + type Res = _1; + } + + impl Add for _0 { + type Res = Rhs::Xor; + type Carry = Rhs::And; + } + + impl Add for _1 { + type Res = ::Xor; + type Carry = Rhs::Or<::And>; + } +} diff --git a/src/typedefs.rs b/src/typedefs.rs new file mode 100644 index 0000000..c26a5f9 --- /dev/null +++ b/src/typedefs.rs @@ -0,0 +1,520 @@ +#![allow(non_camel_case_types)] + +use super::Aint; + +/// A single bit, unsigned integer +pub type bit = Aint; + +/// A 1-bit unsigned integer +pub type u1 = Aint; +/// A 2-bit unsigned integer +pub type u2 = Aint; +/// A 3-bit unsigned integer +pub type u3 = Aint; +/// A 4-bit unsigned integer +pub type u4 = Aint; +/// A 5-bit unsigned integer +pub type u5 = Aint; +/// A 6-bit unsigned integer +pub type u6 = Aint; +/// A 7-bit unsigned integer +pub type u7 = Aint; +/// A 8-bit unsigned integer +pub type u8 = core::primitive::u8; +/// A 9-bit unsigned integer +pub type u9 = Aint; +/// A 10-bit unsigned integer +pub type u10 = Aint; +/// A 11-bit unsigned integer +pub type u11 = Aint; +/// A 12-bit unsigned integer +pub type u12 = Aint; +/// A 13-bit unsigned integer +pub type u13 = Aint; +/// A 14-bit unsigned integer +pub type u14 = Aint; +/// A 15-bit unsigned integer +pub type u15 = Aint; +/// A 16-bit unsigned integer +pub type u16 = core::primitive::u16; +/// A 17-bit unsigned integer +pub type u17 = Aint; +/// A 18-bit unsigned integer +pub type u18 = Aint; +/// A 19-bit unsigned integer +pub type u19 = Aint; +/// A 20-bit unsigned integer +pub type u20 = Aint; +/// A 21-bit unsigned integer +pub type u21 = Aint; +/// A 22-bit unsigned integer +pub type u22 = Aint; +/// A 23-bit unsigned integer +pub type u23 = Aint; +/// A 24-bit unsigned integer +pub type u24 = Aint; +/// A 25-bit unsigned integer +pub type u25 = Aint; +/// A 26-bit unsigned integer +pub type u26 = Aint; +/// A 27-bit unsigned integer +pub type u27 = Aint; +/// A 28-bit unsigned integer +pub type u28 = Aint; +/// A 29-bit unsigned integer +pub type u29 = Aint; +/// A 30-bit unsigned integer +pub type u30 = Aint; +/// A 31-bit unsigned integer +pub type u31 = Aint; +/// A 32-bit unsigned integer +pub type u32 = core::primitive::u32; +/// A 33-bit unsigned integer +pub type u33 = Aint; +/// A 34-bit unsigned integer +pub type u34 = Aint; +/// A 35-bit unsigned integer +pub type u35 = Aint; +/// A 36-bit unsigned integer +pub type u36 = Aint; +/// A 37-bit unsigned integer +pub type u37 = Aint; +/// A 38-bit unsigned integer +pub type u38 = Aint; +/// A 39-bit unsigned integer +pub type u39 = Aint; +/// A 40-bit unsigned integer +pub type u40 = Aint; +/// A 41-bit unsigned integer +pub type u41 = Aint; +/// A 42-bit unsigned integer +pub type u42 = Aint; +/// A 43-bit unsigned integer +pub type u43 = Aint; +/// A 44-bit unsigned integer +pub type u44 = Aint; +/// A 45-bit unsigned integer +pub type u45 = Aint; +/// A 46-bit unsigned integer +pub type u46 = Aint; +/// A 47-bit unsigned integer +pub type u47 = Aint; +/// A 48-bit unsigned integer +pub type u48 = Aint; +/// A 49-bit unsigned integer +pub type u49 = Aint; +/// A 50-bit unsigned integer +pub type u50 = Aint; +/// A 51-bit unsigned integer +pub type u51 = Aint; +/// A 52-bit unsigned integer +pub type u52 = Aint; +/// A 53-bit unsigned integer +pub type u53 = Aint; +/// A 54-bit unsigned integer +pub type u54 = Aint; +/// A 55-bit unsigned integer +pub type u55 = Aint; +/// A 56-bit unsigned integer +pub type u56 = Aint; +/// A 57-bit unsigned integer +pub type u57 = Aint; +/// A 58-bit unsigned integer +pub type u58 = Aint; +/// A 59-bit unsigned integer +pub type u59 = Aint; +/// A 60-bit unsigned integer +pub type u60 = Aint; +/// A 61-bit unsigned integer +pub type u61 = Aint; +/// A 62-bit unsigned integer +pub type u62 = Aint; +/// A 63-bit unsigned integer +pub type u63 = Aint; +/// A 64-bit unsigned integer +pub type u64 = core::primitive::u64; +/// A 65-bit unsigned integer +pub type u65 = Aint; +/// A 66-bit unsigned integer +pub type u66 = Aint; +/// A 67-bit unsigned integer +pub type u67 = Aint; +/// A 68-bit unsigned integer +pub type u68 = Aint; +/// A 69-bit unsigned integer +pub type u69 = Aint; +/// A 70-bit unsigned integer +pub type u70 = Aint; +/// A 71-bit unsigned integer +pub type u71 = Aint; +/// A 72-bit unsigned integer +pub type u72 = Aint; +/// A 73-bit unsigned integer +pub type u73 = Aint; +/// A 74-bit unsigned integer +pub type u74 = Aint; +/// A 75-bit unsigned integer +pub type u75 = Aint; +/// A 76-bit unsigned integer +pub type u76 = Aint; +/// A 77-bit unsigned integer +pub type u77 = Aint; +/// A 78-bit unsigned integer +pub type u78 = Aint; +/// A 79-bit unsigned integer +pub type u79 = Aint; +/// A 80-bit unsigned integer +pub type u80 = Aint; +/// A 81-bit unsigned integer +pub type u81 = Aint; +/// A 82-bit unsigned integer +pub type u82 = Aint; +/// A 83-bit unsigned integer +pub type u83 = Aint; +/// A 84-bit unsigned integer +pub type u84 = Aint; +/// A 85-bit unsigned integer +pub type u85 = Aint; +/// A 86-bit unsigned integer +pub type u86 = Aint; +/// A 87-bit unsigned integer +pub type u87 = Aint; +/// A 88-bit unsigned integer +pub type u88 = Aint; +/// A 89-bit unsigned integer +pub type u89 = Aint; +/// A 90-bit unsigned integer +pub type u90 = Aint; +/// A 91-bit unsigned integer +pub type u91 = Aint; +/// A 92-bit unsigned integer +pub type u92 = Aint; +/// A 93-bit unsigned integer +pub type u93 = Aint; +/// A 94-bit unsigned integer +pub type u94 = Aint; +/// A 95-bit unsigned integer +pub type u95 = Aint; +/// A 96-bit unsigned integer +pub type u96 = Aint; +/// A 97-bit unsigned integer +pub type u97 = Aint; +/// A 98-bit unsigned integer +pub type u98 = Aint; +/// A 99-bit unsigned integer +pub type u99 = Aint; +/// A 100-bit unsigned integer +pub type u100 = Aint; +/// A 101-bit unsigned integer +pub type u101 = Aint; +/// A 102-bit unsigned integer +pub type u102 = Aint; +/// A 103-bit unsigned integer +pub type u103 = Aint; +/// A 104-bit unsigned integer +pub type u104 = Aint; +/// A 105-bit unsigned integer +pub type u105 = Aint; +/// A 106-bit unsigned integer +pub type u106 = Aint; +/// A 107-bit unsigned integer +pub type u107 = Aint; +/// A 108-bit unsigned integer +pub type u108 = Aint; +/// A 109-bit unsigned integer +pub type u109 = Aint; +/// A 110-bit unsigned integer +pub type u110 = Aint; +/// A 111-bit unsigned integer +pub type u111 = Aint; +/// A 112-bit unsigned integer +pub type u112 = Aint; +/// A 113-bit unsigned integer +pub type u113 = Aint; +/// A 114-bit unsigned integer +pub type u114 = Aint; +/// A 115-bit unsigned integer +pub type u115 = Aint; +/// A 116-bit unsigned integer +pub type u116 = Aint; +/// A 117-bit unsigned integer +pub type u117 = Aint; +/// A 118-bit unsigned integer +pub type u118 = Aint; +/// A 119-bit unsigned integer +pub type u119 = Aint; +/// A 120-bit unsigned integer +pub type u120 = Aint; +/// A 121-bit unsigned integer +pub type u121 = Aint; +/// A 122-bit unsigned integer +pub type u122 = Aint; +/// A 123-bit unsigned integer +pub type u123 = Aint; +/// A 124-bit unsigned integer +pub type u124 = Aint; +/// A 125-bit unsigned integer +pub type u125 = Aint; +/// A 126-bit unsigned integer +pub type u126 = Aint; +/// A 127-bit unsigned integer +pub type u127 = Aint; +/// A 128-bit unsigned integer +pub type u128 = core::primitive::u128; + +/// A 1-bit signed integer +pub type i1 = Aint; +/// A 2-bit signed integer +pub type i2 = Aint; +/// A 3-bit signed integer +pub type i3 = Aint; +/// A 4-bit signed integer +pub type i4 = Aint; +/// A 5-bit signed integer +pub type i5 = Aint; +/// A 6-bit signed integer +pub type i6 = Aint; +/// A 7-bit signed integer +pub type i7 = Aint; +/// A 8-bit signed integer +pub type i8 = core::primitive::i8; +/// A 9-bit signed integer +pub type i9 = Aint; +/// A 10-bit signed integer +pub type i10 = Aint; +/// A 11-bit signed integer +pub type i11 = Aint; +/// A 12-bit signed integer +pub type i12 = Aint; +/// A 13-bit signed integer +pub type i13 = Aint; +/// A 14-bit signed integer +pub type i14 = Aint; +/// A 15-bit signed integer +pub type i15 = Aint; +/// A 16-bit signed integer +pub type i16 = core::primitive::i16; +/// A 17-bit signed integer +pub type i17 = Aint; +/// A 18-bit signed integer +pub type i18 = Aint; +/// A 19-bit signed integer +pub type i19 = Aint; +/// A 20-bit signed integer +pub type i20 = Aint; +/// A 21-bit signed integer +pub type i21 = Aint; +/// A 22-bit signed integer +pub type i22 = Aint; +/// A 23-bit signed integer +pub type i23 = Aint; +/// A 24-bit signed integer +pub type i24 = Aint; +/// A 25-bit signed integer +pub type i25 = Aint; +/// A 26-bit signed integer +pub type i26 = Aint; +/// A 27-bit signed integer +pub type i27 = Aint; +/// A 28-bit signed integer +pub type i28 = Aint; +/// A 29-bit signed integer +pub type i29 = Aint; +/// A 30-bit signed integer +pub type i30 = Aint; +/// A 31-bit signed integer +pub type i31 = Aint; +/// A 32-bit signed integer +pub type i32 = core::primitive::i32; +/// A 33-bit signed integer +pub type i33 = Aint; +/// A 34-bit signed integer +pub type i34 = Aint; +/// A 35-bit signed integer +pub type i35 = Aint; +/// A 36-bit signed integer +pub type i36 = Aint; +/// A 37-bit signed integer +pub type i37 = Aint; +/// A 38-bit signed integer +pub type i38 = Aint; +/// A 39-bit signed integer +pub type i39 = Aint; +/// A 40-bit signed integer +pub type i40 = Aint; +/// A 41-bit signed integer +pub type i41 = Aint; +/// A 42-bit signed integer +pub type i42 = Aint; +/// A 43-bit signed integer +pub type i43 = Aint; +/// A 44-bit signed integer +pub type i44 = Aint; +/// A 45-bit signed integer +pub type i45 = Aint; +/// A 46-bit signed integer +pub type i46 = Aint; +/// A 47-bit signed integer +pub type i47 = Aint; +/// A 48-bit signed integer +pub type i48 = Aint; +/// A 49-bit signed integer +pub type i49 = Aint; +/// A 50-bit signed integer +pub type i50 = Aint; +/// A 51-bit signed integer +pub type i51 = Aint; +/// A 52-bit signed integer +pub type i52 = Aint; +/// A 53-bit signed integer +pub type i53 = Aint; +/// A 54-bit signed integer +pub type i54 = Aint; +/// A 55-bit signed integer +pub type i55 = Aint; +/// A 56-bit signed integer +pub type i56 = Aint; +/// A 57-bit signed integer +pub type i57 = Aint; +/// A 58-bit signed integer +pub type i58 = Aint; +/// A 59-bit signed integer +pub type i59 = Aint; +/// A 60-bit signed integer +pub type i60 = Aint; +/// A 61-bit signed integer +pub type i61 = Aint; +/// A 62-bit signed integer +pub type i62 = Aint; +/// A 63-bit signed integer +pub type i63 = Aint; +/// A 64-bit signed integer +pub type i64 = core::primitive::i64; +/// A 65-bit signed integer +pub type i65 = Aint; +/// A 66-bit signed integer +pub type i66 = Aint; +/// A 67-bit signed integer +pub type i67 = Aint; +/// A 68-bit signed integer +pub type i68 = Aint; +/// A 69-bit signed integer +pub type i69 = Aint; +/// A 70-bit signed integer +pub type i70 = Aint; +/// A 71-bit signed integer +pub type i71 = Aint; +/// A 72-bit signed integer +pub type i72 = Aint; +/// A 73-bit signed integer +pub type i73 = Aint; +/// A 74-bit signed integer +pub type i74 = Aint; +/// A 75-bit signed integer +pub type i75 = Aint; +/// A 76-bit signed integer +pub type i76 = Aint; +/// A 77-bit signed integer +pub type i77 = Aint; +/// A 78-bit signed integer +pub type i78 = Aint; +/// A 79-bit signed integer +pub type i79 = Aint; +/// A 80-bit signed integer +pub type i80 = Aint; +/// A 81-bit signed integer +pub type i81 = Aint; +/// A 82-bit signed integer +pub type i82 = Aint; +/// A 83-bit signed integer +pub type i83 = Aint; +/// A 84-bit signed integer +pub type i84 = Aint; +/// A 85-bit signed integer +pub type i85 = Aint; +/// A 86-bit signed integer +pub type i86 = Aint; +/// A 87-bit signed integer +pub type i87 = Aint; +/// A 88-bit signed integer +pub type i88 = Aint; +/// A 89-bit signed integer +pub type i89 = Aint; +/// A 90-bit signed integer +pub type i90 = Aint; +/// A 91-bit signed integer +pub type i91 = Aint; +/// A 92-bit signed integer +pub type i92 = Aint; +/// A 93-bit signed integer +pub type i93 = Aint; +/// A 94-bit signed integer +pub type i94 = Aint; +/// A 95-bit signed integer +pub type i95 = Aint; +/// A 96-bit signed integer +pub type i96 = Aint; +/// A 97-bit signed integer +pub type i97 = Aint; +/// A 98-bit signed integer +pub type i98 = Aint; +/// A 99-bit signed integer +pub type i99 = Aint; +/// A 100-bit signed integer +pub type i100 = Aint; +/// A 101-bit signed integer +pub type i101 = Aint; +/// A 102-bit signed integer +pub type i102 = Aint; +/// A 103-bit signed integer +pub type i103 = Aint; +/// A 104-bit signed integer +pub type i104 = Aint; +/// A 105-bit signed integer +pub type i105 = Aint; +/// A 106-bit signed integer +pub type i106 = Aint; +/// A 107-bit signed integer +pub type i107 = Aint; +/// A 108-bit signed integer +pub type i108 = Aint; +/// A 109-bit signed integer +pub type i109 = Aint; +/// A 110-bit signed integer +pub type i110 = Aint; +/// A 111-bit signed integer +pub type i111 = Aint; +/// A 112-bit signed integer +pub type i112 = Aint; +/// A 113-bit signed integer +pub type i113 = Aint; +/// A 114-bit signed integer +pub type i114 = Aint; +/// A 115-bit signed integer +pub type i115 = Aint; +/// A 116-bit signed integer +pub type i116 = Aint; +/// A 117-bit signed integer +pub type i117 = Aint; +/// A 118-bit signed integer +pub type i118 = Aint; +/// A 119-bit signed integer +pub type i119 = Aint; +/// A 120-bit signed integer +pub type i120 = Aint; +/// A 121-bit signed integer +pub type i121 = Aint; +/// A 122-bit signed integer +pub type i122 = Aint; +/// A 123-bit signed integer +pub type i123 = Aint; +/// A 124-bit signed integer +pub type i124 = Aint; +/// A 125-bit signed integer +pub type i125 = Aint; +/// A 126-bit signed integer +pub type i126 = Aint; +/// A 127-bit signed integer +pub type i127 = Aint; +/// A 128-bit signed integer +pub type i128 = core::primitive::i128; diff --git a/src/width.rs b/src/width.rs new file mode 100644 index 0000000..ba6fc99 --- /dev/null +++ b/src/width.rs @@ -0,0 +1,388 @@ +use crate::tybit::{self, Assert, Bit, _0, _1}; + +pub trait Width { + const WIDTH: u32; + type B7: Bit; + type B6: Bit; + type B5: Bit; + type B4: Bit; + type B3: Bit; + type B2: Bit; + type B1: Bit; + type B0: Bit; + + type Eq: Bit; + type Ne: Bit; + type Lt: Bit; + type Gt: Bit; + type Le: Bit; + type Ge: Bit; + type Add: Width; +} + +pub struct WidthVal( + core::marker::PhantomData<(B7, B6, B5, B4, B3, B2, B1, B0)>, +); + +impl Width + for WidthVal +{ + const WIDTH: u32 = (B7::VALUE << 7) + | (B6::VALUE << 6) + | (B5::VALUE << 5) + | (B4::VALUE << 4) + | (B3::VALUE << 3) + | (B2::VALUE << 2) + | (B1::VALUE << 1) + | B0::VALUE; + type B7 = B7; + type B6 = B6; + type B5 = B5; + type B4 = B4; + type B3 = B3; + type B2 = B2; + type B1 = B1; + type B0 = B0; + + type Eq = tybit::And< + tybit::And< + tybit::And, tybit::Eq>, + tybit::And, tybit::Eq>, + >, + tybit::And< + tybit::And, tybit::Eq>, + tybit::And, tybit::Eq>, + >, + >; + + type Ne = tybit::Not>; + + type Lt = tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Or< + tybit::Lt, + tybit::And< + tybit::Eq, + tybit::Lt, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >; + + type Gt = Rhs::Lt; + + type Le = tybit::Not>; + + type Ge = tybit::Not>; + + type Add = WidthVal< + tybit::Add< + B7, + Rhs::B7, + tybit::AddCarry< + B6, + Rhs::B6, + tybit::AddCarry< + B5, + Rhs::B5, + tybit::AddCarry< + B4, + Rhs::B4, + tybit::AddCarry< + B3, + Rhs::B3, + tybit::AddCarry< + B2, + Rhs::B1, + tybit::AddCarry>, + >, + >, + >, + >, + >, + >, + tybit::Add< + B6, + Rhs::B6, + tybit::AddCarry< + B5, + Rhs::B5, + tybit::AddCarry< + B4, + Rhs::B4, + tybit::AddCarry< + B3, + Rhs::B3, + tybit::AddCarry< + B2, + Rhs::B1, + tybit::AddCarry>, + >, + >, + >, + >, + >, + tybit::Add< + B5, + Rhs::B5, + tybit::AddCarry< + B4, + Rhs::B4, + tybit::AddCarry< + B3, + Rhs::B3, + tybit::AddCarry< + B2, + Rhs::B1, + tybit::AddCarry>, + >, + >, + >, + >, + tybit::Add< + B4, + Rhs::B4, + tybit::AddCarry< + B3, + Rhs::B3, + tybit::AddCarry< + B2, + Rhs::B1, + tybit::AddCarry>, + >, + >, + >, + tybit::Add< + B3, + Rhs::B3, + tybit::AddCarry< + B2, + Rhs::B1, + tybit::AddCarry>, + >, + >, + tybit::Add>>, + tybit::Add>, + tybit::Add, + >; +} + +pub trait WidthEq: Width {} +pub trait WidthNe: Width {} +pub trait WidthLt: Width {} +pub trait WidthGt: Width {} +pub trait WidthLe: Width {} +pub trait WidthGe: Width {} + +impl WidthEq for L where L::Eq: Assert {} + +impl WidthNe for L where L::Ne: Assert {} + +impl WidthLt for L where L::Lt: Assert {} + +impl WidthGt for L where L::Gt: Assert {} + +impl WidthLe for L where L::Le: Assert {} + +impl WidthGe for L where L::Ge: Assert {} + +pub struct W; + +macro_rules! impl_w { + ($width:literal, $b7:ident, $b6:ident, $b5:ident, $b4:ident, $b3:ident, $b2:ident, $b1:ident, $b0:ident) => { + impl Width for W<$width> { + const WIDTH: u32 = $width; + type B7 = $b7; + type B6 = $b6; + type B5 = $b5; + type B4 = $b4; + type B3 = $b3; + type B2 = $b2; + type B1 = $b1; + type B0 = $b0; + + type Eq = + as Width>::Eq; + + type Ne = + as Width>::Ne; + + type Lt = + as Width>::Lt; + + type Gt = + as Width>::Gt; + + type Le = + as Width>::Le; + + type Ge = + as Width>::Ge; + + type Add = + as Width>::Add; + } + }; +} + +impl_w!(0, _0, _0, _0, _0, _0, _0, _0, _0); +impl_w!(1, _0, _0, _0, _0, _0, _0, _0, _1); +impl_w!(2, _0, _0, _0, _0, _0, _0, _1, _0); +impl_w!(3, _0, _0, _0, _0, _0, _0, _1, _1); +impl_w!(4, _0, _0, _0, _0, _0, _1, _0, _0); +impl_w!(5, _0, _0, _0, _0, _0, _1, _0, _1); +impl_w!(6, _0, _0, _0, _0, _0, _1, _1, _0); +impl_w!(7, _0, _0, _0, _0, _0, _1, _1, _1); +impl_w!(8, _0, _0, _0, _0, _1, _0, _0, _0); +impl_w!(9, _0, _0, _0, _0, _1, _0, _0, _1); +impl_w!(10, _0, _0, _0, _0, _1, _0, _1, _0); +impl_w!(11, _0, _0, _0, _0, _1, _0, _1, _1); +impl_w!(12, _0, _0, _0, _0, _1, _1, _0, _0); +impl_w!(13, _0, _0, _0, _0, _1, _1, _0, _1); +impl_w!(14, _0, _0, _0, _0, _1, _1, _1, _0); +impl_w!(15, _0, _0, _0, _0, _1, _1, _1, _1); +impl_w!(16, _0, _0, _0, _1, _0, _0, _0, _0); +impl_w!(17, _0, _0, _0, _1, _0, _0, _0, _1); +impl_w!(18, _0, _0, _0, _1, _0, _0, _1, _0); +impl_w!(19, _0, _0, _0, _1, _0, _0, _1, _1); +impl_w!(20, _0, _0, _0, _1, _0, _1, _0, _0); +impl_w!(21, _0, _0, _0, _1, _0, _1, _0, _1); +impl_w!(22, _0, _0, _0, _1, _0, _1, _1, _0); +impl_w!(23, _0, _0, _0, _1, _0, _1, _1, _1); +impl_w!(24, _0, _0, _0, _1, _1, _0, _0, _0); +impl_w!(25, _0, _0, _0, _1, _1, _0, _0, _1); +impl_w!(26, _0, _0, _0, _1, _1, _0, _1, _0); +impl_w!(27, _0, _0, _0, _1, _1, _0, _1, _1); +impl_w!(28, _0, _0, _0, _1, _1, _1, _0, _0); +impl_w!(29, _0, _0, _0, _1, _1, _1, _0, _1); +impl_w!(30, _0, _0, _0, _1, _1, _1, _1, _0); +impl_w!(31, _0, _0, _0, _1, _1, _1, _1, _1); +impl_w!(32, _0, _0, _1, _0, _0, _0, _0, _0); +impl_w!(33, _0, _0, _1, _0, _0, _0, _0, _1); +impl_w!(34, _0, _0, _1, _0, _0, _0, _1, _0); +impl_w!(35, _0, _0, _1, _0, _0, _0, _1, _1); +impl_w!(36, _0, _0, _1, _0, _0, _1, _0, _0); +impl_w!(37, _0, _0, _1, _0, _0, _1, _0, _1); +impl_w!(38, _0, _0, _1, _0, _0, _1, _1, _0); +impl_w!(39, _0, _0, _1, _0, _0, _1, _1, _1); +impl_w!(40, _0, _0, _1, _0, _1, _0, _0, _0); +impl_w!(41, _0, _0, _1, _0, _1, _0, _0, _1); +impl_w!(42, _0, _0, _1, _0, _1, _0, _1, _0); +impl_w!(43, _0, _0, _1, _0, _1, _0, _1, _1); +impl_w!(44, _0, _0, _1, _0, _1, _1, _0, _0); +impl_w!(45, _0, _0, _1, _0, _1, _1, _0, _1); +impl_w!(46, _0, _0, _1, _0, _1, _1, _1, _0); +impl_w!(47, _0, _0, _1, _0, _1, _1, _1, _1); +impl_w!(48, _0, _0, _1, _1, _0, _0, _0, _0); +impl_w!(49, _0, _0, _1, _1, _0, _0, _0, _1); +impl_w!(50, _0, _0, _1, _1, _0, _0, _1, _0); +impl_w!(51, _0, _0, _1, _1, _0, _0, _1, _1); +impl_w!(52, _0, _0, _1, _1, _0, _1, _0, _0); +impl_w!(53, _0, _0, _1, _1, _0, _1, _0, _1); +impl_w!(54, _0, _0, _1, _1, _0, _1, _1, _0); +impl_w!(55, _0, _0, _1, _1, _0, _1, _1, _1); +impl_w!(56, _0, _0, _1, _1, _1, _0, _0, _0); +impl_w!(57, _0, _0, _1, _1, _1, _0, _0, _1); +impl_w!(58, _0, _0, _1, _1, _1, _0, _1, _0); +impl_w!(59, _0, _0, _1, _1, _1, _0, _1, _1); +impl_w!(60, _0, _0, _1, _1, _1, _1, _0, _0); +impl_w!(61, _0, _0, _1, _1, _1, _1, _0, _1); +impl_w!(62, _0, _0, _1, _1, _1, _1, _1, _0); +impl_w!(63, _0, _0, _1, _1, _1, _1, _1, _1); +impl_w!(64, _0, _1, _0, _0, _0, _0, _0, _0); +impl_w!(65, _0, _1, _0, _0, _0, _0, _0, _1); +impl_w!(66, _0, _1, _0, _0, _0, _0, _1, _0); +impl_w!(67, _0, _1, _0, _0, _0, _0, _1, _1); +impl_w!(68, _0, _1, _0, _0, _0, _1, _0, _0); +impl_w!(69, _0, _1, _0, _0, _0, _1, _0, _1); +impl_w!(70, _0, _1, _0, _0, _0, _1, _1, _0); +impl_w!(71, _0, _1, _0, _0, _0, _1, _1, _1); +impl_w!(72, _0, _1, _0, _0, _1, _0, _0, _0); +impl_w!(73, _0, _1, _0, _0, _1, _0, _0, _1); +impl_w!(74, _0, _1, _0, _0, _1, _0, _1, _0); +impl_w!(75, _0, _1, _0, _0, _1, _0, _1, _1); +impl_w!(76, _0, _1, _0, _0, _1, _1, _0, _0); +impl_w!(77, _0, _1, _0, _0, _1, _1, _0, _1); +impl_w!(78, _0, _1, _0, _0, _1, _1, _1, _0); +impl_w!(79, _0, _1, _0, _0, _1, _1, _1, _1); +impl_w!(80, _0, _1, _0, _1, _0, _0, _0, _0); +impl_w!(81, _0, _1, _0, _1, _0, _0, _0, _1); +impl_w!(82, _0, _1, _0, _1, _0, _0, _1, _0); +impl_w!(83, _0, _1, _0, _1, _0, _0, _1, _1); +impl_w!(84, _0, _1, _0, _1, _0, _1, _0, _0); +impl_w!(85, _0, _1, _0, _1, _0, _1, _0, _1); +impl_w!(86, _0, _1, _0, _1, _0, _1, _1, _0); +impl_w!(87, _0, _1, _0, _1, _0, _1, _1, _1); +impl_w!(88, _0, _1, _0, _1, _1, _0, _0, _0); +impl_w!(89, _0, _1, _0, _1, _1, _0, _0, _1); +impl_w!(90, _0, _1, _0, _1, _1, _0, _1, _0); +impl_w!(91, _0, _1, _0, _1, _1, _0, _1, _1); +impl_w!(92, _0, _1, _0, _1, _1, _1, _0, _0); +impl_w!(93, _0, _1, _0, _1, _1, _1, _0, _1); +impl_w!(94, _0, _1, _0, _1, _1, _1, _1, _0); +impl_w!(95, _0, _1, _0, _1, _1, _1, _1, _1); +impl_w!(96, _0, _1, _1, _0, _0, _0, _0, _0); +impl_w!(97, _0, _1, _1, _0, _0, _0, _0, _1); +impl_w!(98, _0, _1, _1, _0, _0, _0, _1, _0); +impl_w!(99, _0, _1, _1, _0, _0, _0, _1, _1); +impl_w!(100, _0, _1, _1, _0, _0, _1, _0, _0); +impl_w!(101, _0, _1, _1, _0, _0, _1, _0, _1); +impl_w!(102, _0, _1, _1, _0, _0, _1, _1, _0); +impl_w!(103, _0, _1, _1, _0, _0, _1, _1, _1); +impl_w!(104, _0, _1, _1, _0, _1, _0, _0, _0); +impl_w!(105, _0, _1, _1, _0, _1, _0, _0, _1); +impl_w!(106, _0, _1, _1, _0, _1, _0, _1, _0); +impl_w!(107, _0, _1, _1, _0, _1, _0, _1, _1); +impl_w!(108, _0, _1, _1, _0, _1, _1, _0, _0); +impl_w!(109, _0, _1, _1, _0, _1, _1, _0, _1); +impl_w!(110, _0, _1, _1, _0, _1, _1, _1, _0); +impl_w!(111, _0, _1, _1, _0, _1, _1, _1, _1); +impl_w!(112, _0, _1, _1, _1, _0, _0, _0, _0); +impl_w!(113, _0, _1, _1, _1, _0, _0, _0, _1); +impl_w!(114, _0, _1, _1, _1, _0, _0, _1, _0); +impl_w!(115, _0, _1, _1, _1, _0, _0, _1, _1); +impl_w!(116, _0, _1, _1, _1, _0, _1, _0, _0); +impl_w!(117, _0, _1, _1, _1, _0, _1, _0, _1); +impl_w!(118, _0, _1, _1, _1, _0, _1, _1, _0); +impl_w!(119, _0, _1, _1, _1, _0, _1, _1, _1); +impl_w!(120, _0, _1, _1, _1, _1, _0, _0, _0); +impl_w!(121, _0, _1, _1, _1, _1, _0, _0, _1); +impl_w!(122, _0, _1, _1, _1, _1, _0, _1, _0); +impl_w!(123, _0, _1, _1, _1, _1, _0, _1, _1); +impl_w!(124, _0, _1, _1, _1, _1, _1, _0, _0); +impl_w!(125, _0, _1, _1, _1, _1, _1, _0, _1); +impl_w!(126, _0, _1, _1, _1, _1, _1, _1, _0); +impl_w!(127, _0, _1, _1, _1, _1, _1, _1, _1); +impl_w!(128, _1, _0, _0, _0, _0, _0, _0, _0); diff --git a/src/wrapping.rs b/src/wrapping.rs new file mode 100644 index 0000000..5b25e9d --- /dev/null +++ b/src/wrapping.rs @@ -0,0 +1,930 @@ +use crate::{prim::Prim, sealed::Sealed, Aint}; + +/// Wrapping conversion from one type into another. +/// +/// When the source value is too large to be represented +/// by the destination type, the resulting value is +/// calculated by wrapping the source value as though +/// it were calculated with wrapping operations, such +/// as `i32::wrapping_add`. In practice, the source value +/// is simply truncated, bitwise. +/// +/// # Example: +/// ``` +/// # use aint::WrappingFrom; +/// let value = u8::wrapping_from(0x1234); +/// assert_eq!(value, 0x34); +/// ``` +pub trait WrappingFrom { + fn wrapping_from(value: T) -> Self; +} + +/// Wrapping conversion from one type into another. +/// +/// When the source value is too large to be represented +/// by the destination type, the resulting value is +/// calculated by wrapping the source value as though +/// it were calculated with wrapping operations, such +/// as `i32::wrapping_add`. In practice, the source value +/// is simply truncated, bitwise. +/// +/// # Example: +/// ``` +/// # use aint::WrappingInto; +/// let value: u8 = 0x1234.wrapping_into(); +/// assert_eq!(value, 0x34); +/// ``` +pub trait WrappingInto { + fn wrapping_into(self) -> T; +} + +impl WrappingInto for F +where + T: WrappingFrom, +{ + fn wrapping_into(self) -> T { + T::wrapping_from(self) + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: u8) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: u16) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: u32) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: u64) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: u128) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: usize) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: i8) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: i16) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: i32) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: i64) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: i128) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u8 { + fn wrapping_from(value: isize) -> u8 { + value as u8 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: u8) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: u16) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: u32) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: u64) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: u128) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: usize) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: i8) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: i16) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: i32) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: i64) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: i128) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u16 { + fn wrapping_from(value: isize) -> u16 { + value as u16 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: u8) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: u16) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: u32) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: u64) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: u128) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: usize) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: i8) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: i16) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: i32) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: i64) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: i128) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u32 { + fn wrapping_from(value: isize) -> u32 { + value as u32 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: u8) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: u16) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: u32) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: u64) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: u128) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: usize) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: i8) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: i16) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: i32) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: i64) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: i128) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u64 { + fn wrapping_from(value: isize) -> u64 { + value as u64 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: u8) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: u16) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: u32) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: u64) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: u128) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: usize) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: i8) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: i16) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: i32) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: i64) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: i128) -> u128 { + value as u128 + } +} + +impl WrappingFrom for u128 { + fn wrapping_from(value: isize) -> u128 { + value as u128 + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: u8) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: u16) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: u32) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: u64) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: u128) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: usize) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: i8) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: i16) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: i32) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: i64) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: i128) -> usize { + value as usize + } +} + +impl WrappingFrom for usize { + fn wrapping_from(value: isize) -> usize { + value as usize + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: u8) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: u16) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: u32) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: u64) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: u128) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: usize) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: i8) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: i16) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: i32) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: i64) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: i128) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i8 { + fn wrapping_from(value: isize) -> i8 { + value as i8 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: u8) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: u16) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: u32) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: u64) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: u128) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: usize) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: i8) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: i16) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: i32) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: i64) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: i128) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i16 { + fn wrapping_from(value: isize) -> i16 { + value as i16 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: u8) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: u16) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: u32) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: u64) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: u128) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: usize) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: i8) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: i16) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: i32) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: i64) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: i128) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i32 { + fn wrapping_from(value: isize) -> i32 { + value as i32 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: u8) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: u16) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: u32) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: u64) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: u128) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: usize) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: i8) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: i16) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: i32) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: i64) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: i128) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i64 { + fn wrapping_from(value: isize) -> i64 { + value as i64 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: u8) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: u16) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: u32) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: u64) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: u128) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: usize) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: i8) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: i16) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: i32) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: i64) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: i128) -> i128 { + value as i128 + } +} + +impl WrappingFrom for i128 { + fn wrapping_from(value: isize) -> i128 { + value as i128 + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: u8) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: u16) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: u32) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: u64) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: u128) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: usize) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: i8) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: i16) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: i32) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: i64) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: i128) -> isize { + value as isize + } +} + +impl WrappingFrom for isize { + fn wrapping_from(value: isize) -> isize { + value as isize + } +} + +impl WrappingFrom for Aint +where + R: WrappingFrom, +{ + fn wrapping_from(value: F) -> Self { + Self::_new_wrapping(value.wrapping_into()) + } +} + +impl WrappingFrom> for T +where + T: WrappingFrom, +{ + fn wrapping_from(value: Aint) -> Self { + value.0.wrapping_into() + } +}