Skip to main content

libm/math/support/
int_traits.rs

1use core::{cmp, fmt, ops};
2
3mod narrowing_div;
4pub use narrowing_div::NarrowingDiv;
5
6/// Minimal integer implementations needed on all integer types, including wide integers.
7#[allow(dead_code)] // Some constants are only used with tests
8pub trait MinInt:
9    Copy
10    + fmt::Debug
11    + ops::BitOr<Output = Self>
12    + ops::Not<Output = Self>
13    + ops::Shl<u32, Output = Self>
14{
15    /// Type with the same width but other signedness
16    type OtherSign: MinInt;
17    /// Unsigned version of Self
18    type Unsigned: MinInt;
19
20    /// If `Self` is a signed integer
21    const SIGNED: bool;
22
23    /// The bitwidth of the int type
24    const BITS: u32;
25
26    const ZERO: Self;
27    const ONE: Self;
28    const MIN: Self;
29    const MAX: Self;
30}
31
32/// Access the associated `OtherSign` type from an int (helper to avoid ambiguous associated
33/// types).
34pub type OtherSign<I> = <I as MinInt>::OtherSign;
35
36/// Trait for some basic operations on integers
37#[allow(dead_code)]
38pub trait Int:
39    MinInt
40    + fmt::Display
41    + fmt::Binary
42    + fmt::LowerHex
43    + ops::AddAssign
44    + ops::SubAssign
45    + ops::MulAssign
46    + ops::DivAssign
47    + ops::RemAssign
48    + ops::BitAndAssign
49    + ops::BitOrAssign
50    + ops::BitXorAssign
51    + ops::ShlAssign<i32>
52    + ops::ShlAssign<u32>
53    + ops::ShrAssign<u32>
54    + ops::ShrAssign<i32>
55    + ops::Add<Output = Self>
56    + ops::Sub<Output = Self>
57    + ops::Mul<Output = Self>
58    + ops::Div<Output = Self>
59    + ops::Rem<Output = Self>
60    + ops::Shl<i32, Output = Self>
61    + ops::Shl<u32, Output = Self>
62    + ops::Shr<i32, Output = Self>
63    + ops::Shr<u32, Output = Self>
64    + ops::BitXor<Output = Self>
65    + ops::BitAnd<Output = Self>
66    + cmp::Ord
67    + From<bool>
68    + CastFrom<i32>
69    + CastFrom<u16>
70    + CastFrom<u32>
71    + CastFrom<u8>
72    + CastFrom<usize>
73    + CastInto<i32>
74    + CastInto<u16>
75    + CastInto<u32>
76    + CastInto<u8>
77    + CastInto<usize>
78{
79    fn signed(self) -> OtherSign<Self::Unsigned>;
80    fn unsigned(self) -> Self::Unsigned;
81    fn from_unsigned(unsigned: Self::Unsigned) -> Self;
82    fn abs(self) -> Self;
83    fn unsigned_abs(self) -> Self::Unsigned;
84
85    fn from_bool(b: bool) -> Self;
86
87    /// Prevents the need for excessive conversions between signed and unsigned
88    fn logical_shr(self, other: u32) -> Self;
89
90    /// Absolute difference between two integers.
91    fn abs_diff(self, other: Self) -> Self::Unsigned;
92
93    // copied from primitive integers, but put in a trait
94    fn is_zero(self) -> bool;
95    fn checked_add(self, other: Self) -> Option<Self>;
96    fn checked_sub(self, other: Self) -> Option<Self>;
97    fn wrapping_neg(self) -> Self;
98    fn wrapping_add(self, other: Self) -> Self;
99    fn wrapping_mul(self, other: Self) -> Self;
100    fn wrapping_sub(self, other: Self) -> Self;
101    fn wrapping_shl(self, other: u32) -> Self;
102    fn wrapping_shr(self, other: u32) -> Self;
103    fn rotate_left(self, other: u32) -> Self;
104    fn overflowing_add(self, other: Self) -> (Self, bool);
105    fn overflowing_sub(self, other: Self) -> (Self, bool);
106    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool);
107    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool);
108    fn leading_zeros(self) -> u32;
109    fn trailing_zeros(self) -> u32;
110    fn ilog2(self) -> u32;
111}
112
113macro_rules! int_impl_common {
114    ($ty:ty) => {
115        fn from_bool(b: bool) -> Self {
116            b as $ty
117        }
118
119        fn logical_shr(self, other: u32) -> Self {
120            Self::from_unsigned(self.unsigned().wrapping_shr(other))
121        }
122
123        fn is_zero(self) -> bool {
124            self == Self::ZERO
125        }
126
127        fn checked_add(self, other: Self) -> Option<Self> {
128            self.checked_add(other)
129        }
130
131        fn checked_sub(self, other: Self) -> Option<Self> {
132            self.checked_sub(other)
133        }
134
135        fn wrapping_neg(self) -> Self {
136            <Self>::wrapping_neg(self)
137        }
138
139        fn wrapping_add(self, other: Self) -> Self {
140            <Self>::wrapping_add(self, other)
141        }
142
143        fn wrapping_mul(self, other: Self) -> Self {
144            <Self>::wrapping_mul(self, other)
145        }
146
147        fn wrapping_sub(self, other: Self) -> Self {
148            <Self>::wrapping_sub(self, other)
149        }
150
151        fn wrapping_shl(self, other: u32) -> Self {
152            <Self>::wrapping_shl(self, other)
153        }
154
155        fn wrapping_shr(self, other: u32) -> Self {
156            <Self>::wrapping_shr(self, other)
157        }
158
159        fn rotate_left(self, other: u32) -> Self {
160            <Self>::rotate_left(self, other)
161        }
162
163        fn overflowing_add(self, other: Self) -> (Self, bool) {
164            <Self>::overflowing_add(self, other)
165        }
166
167        fn overflowing_sub(self, other: Self) -> (Self, bool) {
168            <Self>::overflowing_sub(self, other)
169        }
170
171        fn leading_zeros(self) -> u32 {
172            <Self>::leading_zeros(self)
173        }
174
175        fn trailing_zeros(self) -> u32 {
176            <Self>::trailing_zeros(self)
177        }
178
179        fn ilog2(self) -> u32 {
180            // On our older MSRV, this resolves to the trait method. Which won't actually work,
181            // but this is only called behind other gates.
182            #[allow(clippy::incompatible_msrv)]
183            <Self>::ilog2(self)
184        }
185
186        fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
187            let (ab, of1) = self.overflowing_add(other);
188            let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
189            // `of1 && of2` is possible with signed integers if a negative sum
190            // overflows to `MAX` and adding the carry overflows again back to `MIN`
191            (abc, of1 ^ of2)
192        }
193
194        fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
195            let (ab, of1) = self.overflowing_sub(other);
196            let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
197            (abc, of1 ^ of2)
198        }
199    };
200}
201
202macro_rules! int_impl {
203    ($ity:ty, $uty:ty) => {
204        impl MinInt for $uty {
205            type OtherSign = $ity;
206            type Unsigned = $uty;
207
208            const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
209            const SIGNED: bool = Self::MIN != Self::ZERO;
210
211            const ZERO: Self = 0;
212            const ONE: Self = 1;
213            const MIN: Self = <Self>::MIN;
214            const MAX: Self = <Self>::MAX;
215        }
216
217        impl Int for $uty {
218            fn signed(self) -> $ity {
219                self as $ity
220            }
221
222            fn unsigned(self) -> Self {
223                self
224            }
225
226            fn abs(self) -> Self {
227                unimplemented!()
228            }
229
230            fn unsigned_abs(self) -> Self {
231                unimplemented!()
232            }
233
234            // It makes writing macros easier if this is implemented for both signed and unsigned
235            #[allow(clippy::wrong_self_convention)]
236            fn from_unsigned(me: $uty) -> Self {
237                me
238            }
239
240            fn abs_diff(self, other: Self) -> Self {
241                self.abs_diff(other)
242            }
243
244            int_impl_common!($uty);
245        }
246
247        impl MinInt for $ity {
248            type OtherSign = $uty;
249            type Unsigned = $uty;
250
251            const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
252            const SIGNED: bool = Self::MIN != Self::ZERO;
253
254            const ZERO: Self = 0;
255            const ONE: Self = 1;
256            const MIN: Self = <Self>::MIN;
257            const MAX: Self = <Self>::MAX;
258        }
259
260        impl Int for $ity {
261            fn signed(self) -> Self {
262                self
263            }
264
265            fn unsigned(self) -> $uty {
266                self as $uty
267            }
268
269            fn abs(self) -> Self {
270                self.abs()
271            }
272
273            fn unsigned_abs(self) -> Self::Unsigned {
274                self.unsigned_abs()
275            }
276
277            fn from_unsigned(me: $uty) -> Self {
278                me as $ity
279            }
280
281            fn abs_diff(self, other: Self) -> $uty {
282                self.abs_diff(other)
283            }
284
285            int_impl_common!($ity);
286        }
287    };
288}
289
290impl MinInt for usize {
    type OtherSign = isize;
    type Unsigned = usize;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for usize {
    fn signed(self) -> isize { self as isize }
    fn unsigned(self) -> Self { self }
    fn abs(self) -> Self { ::core::panicking::panic("not implemented") }
    fn unsigned_abs(self) -> Self {
        ::core::panicking::panic("not implemented")
    }
    #[allow(clippy :: wrong_self_convention)]
    fn from_unsigned(me: usize) -> Self { me }
    fn abs_diff(self, other: Self) -> Self { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as usize }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}
impl MinInt for isize {
    type OtherSign = usize;
    type Unsigned = usize;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for isize {
    fn signed(self) -> Self { self }
    fn unsigned(self) -> usize { self as usize }
    fn abs(self) -> Self { self.abs() }
    fn unsigned_abs(self) -> Self::Unsigned { self.unsigned_abs() }
    fn from_unsigned(me: usize) -> Self { me as isize }
    fn abs_diff(self, other: Self) -> usize { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as isize }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}int_impl!(isize, usize);
291impl MinInt for u8 {
    type OtherSign = i8;
    type Unsigned = u8;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for u8 {
    fn signed(self) -> i8 { self as i8 }
    fn unsigned(self) -> Self { self }
    fn abs(self) -> Self { ::core::panicking::panic("not implemented") }
    fn unsigned_abs(self) -> Self {
        ::core::panicking::panic("not implemented")
    }
    #[allow(clippy :: wrong_self_convention)]
    fn from_unsigned(me: u8) -> Self { me }
    fn abs_diff(self, other: Self) -> Self { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as u8 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}
impl MinInt for i8 {
    type OtherSign = u8;
    type Unsigned = u8;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for i8 {
    fn signed(self) -> Self { self }
    fn unsigned(self) -> u8 { self as u8 }
    fn abs(self) -> Self { self.abs() }
    fn unsigned_abs(self) -> Self::Unsigned { self.unsigned_abs() }
    fn from_unsigned(me: u8) -> Self { me as i8 }
    fn abs_diff(self, other: Self) -> u8 { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as i8 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}int_impl!(i8, u8);
292impl MinInt for u16 {
    type OtherSign = i16;
    type Unsigned = u16;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for u16 {
    fn signed(self) -> i16 { self as i16 }
    fn unsigned(self) -> Self { self }
    fn abs(self) -> Self { ::core::panicking::panic("not implemented") }
    fn unsigned_abs(self) -> Self {
        ::core::panicking::panic("not implemented")
    }
    #[allow(clippy :: wrong_self_convention)]
    fn from_unsigned(me: u16) -> Self { me }
    fn abs_diff(self, other: Self) -> Self { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as u16 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}
impl MinInt for i16 {
    type OtherSign = u16;
    type Unsigned = u16;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for i16 {
    fn signed(self) -> Self { self }
    fn unsigned(self) -> u16 { self as u16 }
    fn abs(self) -> Self { self.abs() }
    fn unsigned_abs(self) -> Self::Unsigned { self.unsigned_abs() }
    fn from_unsigned(me: u16) -> Self { me as i16 }
    fn abs_diff(self, other: Self) -> u16 { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as i16 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}int_impl!(i16, u16);
293impl MinInt for u32 {
    type OtherSign = i32;
    type Unsigned = u32;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for u32 {
    fn signed(self) -> i32 { self as i32 }
    fn unsigned(self) -> Self { self }
    fn abs(self) -> Self { ::core::panicking::panic("not implemented") }
    fn unsigned_abs(self) -> Self {
        ::core::panicking::panic("not implemented")
    }
    #[allow(clippy :: wrong_self_convention)]
    fn from_unsigned(me: u32) -> Self { me }
    fn abs_diff(self, other: Self) -> Self { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as u32 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}
impl MinInt for i32 {
    type OtherSign = u32;
    type Unsigned = u32;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for i32 {
    fn signed(self) -> Self { self }
    fn unsigned(self) -> u32 { self as u32 }
    fn abs(self) -> Self { self.abs() }
    fn unsigned_abs(self) -> Self::Unsigned { self.unsigned_abs() }
    fn from_unsigned(me: u32) -> Self { me as i32 }
    fn abs_diff(self, other: Self) -> u32 { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as i32 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}int_impl!(i32, u32);
294impl MinInt for u64 {
    type OtherSign = i64;
    type Unsigned = u64;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for u64 {
    fn signed(self) -> i64 { self as i64 }
    fn unsigned(self) -> Self { self }
    fn abs(self) -> Self { ::core::panicking::panic("not implemented") }
    fn unsigned_abs(self) -> Self {
        ::core::panicking::panic("not implemented")
    }
    #[allow(clippy :: wrong_self_convention)]
    fn from_unsigned(me: u64) -> Self { me }
    fn abs_diff(self, other: Self) -> Self { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as u64 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}
impl MinInt for i64 {
    type OtherSign = u64;
    type Unsigned = u64;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for i64 {
    fn signed(self) -> Self { self }
    fn unsigned(self) -> u64 { self as u64 }
    fn abs(self) -> Self { self.abs() }
    fn unsigned_abs(self) -> Self::Unsigned { self.unsigned_abs() }
    fn from_unsigned(me: u64) -> Self { me as i64 }
    fn abs_diff(self, other: Self) -> u64 { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as i64 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}int_impl!(i64, u64);
295impl MinInt for u128 {
    type OtherSign = i128;
    type Unsigned = u128;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for u128 {
    fn signed(self) -> i128 { self as i128 }
    fn unsigned(self) -> Self { self }
    fn abs(self) -> Self { ::core::panicking::panic("not implemented") }
    fn unsigned_abs(self) -> Self {
        ::core::panicking::panic("not implemented")
    }
    #[allow(clippy :: wrong_self_convention)]
    fn from_unsigned(me: u128) -> Self { me }
    fn abs_diff(self, other: Self) -> Self { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as u128 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}
impl MinInt for i128 {
    type OtherSign = u128;
    type Unsigned = u128;
    const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
    const SIGNED: bool = Self::MIN != Self::ZERO;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MIN: Self = <Self>::MIN;
    const MAX: Self = <Self>::MAX;
}
impl Int for i128 {
    fn signed(self) -> Self { self }
    fn unsigned(self) -> u128 { self as u128 }
    fn abs(self) -> Self { self.abs() }
    fn unsigned_abs(self) -> Self::Unsigned { self.unsigned_abs() }
    fn from_unsigned(me: u128) -> Self { me as i128 }
    fn abs_diff(self, other: Self) -> u128 { self.abs_diff(other) }
    fn from_bool(b: bool) -> Self { b as i128 }
    fn logical_shr(self, other: u32) -> Self {
        Self::from_unsigned(self.unsigned().wrapping_shr(other))
    }
    fn is_zero(self) -> bool { self == Self::ZERO }
    fn checked_add(self, other: Self) -> Option<Self> {
        self.checked_add(other)
    }
    fn checked_sub(self, other: Self) -> Option<Self> {
        self.checked_sub(other)
    }
    fn wrapping_neg(self) -> Self { <Self>::wrapping_neg(self) }
    fn wrapping_add(self, other: Self) -> Self {
        <Self>::wrapping_add(self, other)
    }
    fn wrapping_mul(self, other: Self) -> Self {
        <Self>::wrapping_mul(self, other)
    }
    fn wrapping_sub(self, other: Self) -> Self {
        <Self>::wrapping_sub(self, other)
    }
    fn wrapping_shl(self, other: u32) -> Self {
        <Self>::wrapping_shl(self, other)
    }
    fn wrapping_shr(self, other: u32) -> Self {
        <Self>::wrapping_shr(self, other)
    }
    fn rotate_left(self, other: u32) -> Self {
        <Self>::rotate_left(self, other)
    }
    fn overflowing_add(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_add(self, other)
    }
    fn overflowing_sub(self, other: Self) -> (Self, bool) {
        <Self>::overflowing_sub(self, other)
    }
    fn leading_zeros(self) -> u32 { <Self>::leading_zeros(self) }
    fn trailing_zeros(self) -> u32 { <Self>::trailing_zeros(self) }
    fn ilog2(self) -> u32 {

        #[allow(clippy :: incompatible_msrv)]
        <Self>::ilog2(self)
    }
    fn carrying_add(self, other: Self, carry: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_add(other);
        let (abc, of2) = ab.overflowing_add(Self::from_bool(carry));
        (abc, of1 ^ of2)
    }
    fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool) {
        let (ab, of1) = self.overflowing_sub(other);
        let (abc, of2) = ab.overflowing_sub(Self::from_bool(borrow));
        (abc, of1 ^ of2)
    }
}int_impl!(i128, u128);
296
297/// Trait for integers twice the bit width of another integer. This is implemented for all
298/// primitives except for `u8`, because there is not a smaller primitive.
299pub trait DInt:
300    MinInt
301    + ops::Add<Output = Self>
302    + ops::Sub<Output = Self>
303    + ops::Shl<u32, Output = Self>
304    + ops::Shr<u32, Output = Self>
305    + Ord
306{
307    /// Integer that is half the bit width of the integer this trait is implemented for
308    type H: HInt<D = Self>;
309
310    /// Returns the low half of `self`
311    fn lo(self) -> Self::H;
312    /// Returns the high half of `self`
313    fn hi(self) -> Self::H;
314    /// Returns the low and high halves of `self` as a tuple
315    fn lo_hi(self) -> (Self::H, Self::H) {
316        (self.lo(), self.hi())
317    }
318    /// Constructs an integer using lower and higher half parts
319    #[allow(unused)]
320    fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {
321        lo.zero_widen() | hi.widen_hi()
322    }
323}
324
325/// Trait for integers half the bit width of another integer. This is implemented for all
326/// primitives except for `u128`, because it there is not a larger primitive.
327pub trait HInt: Int {
328    /// Integer that is double the bit width of the integer this trait is implemented for
329    type D: DInt<H = Self> + MinInt;
330
331    // NB: some of the below methods could have default implementations (e.g. `widen_hi`), but for
332    // unknown reasons this can cause infinite recursion when optimizations are disabled. See
333    // <https://github.com/rust-lang/compiler-builtins/pull/707> for context.
334
335    /// Widens (using default extension) the integer to have double bit width
336    fn widen(self) -> Self::D;
337    /// Widens (zero extension only) the integer to have double bit width. This is needed to get
338    /// around problems with associated type bounds (such as `Int<Othersign: DInt>`) being unstable
339    fn zero_widen(self) -> Self::D;
340    /// Widens the integer to have double bit width and shifts the integer into the higher bits
341    #[allow(unused)]
342    fn widen_hi(self) -> Self::D;
343    /// Widening multiplication with zero widening. This cannot overflow.
344    fn zero_widen_mul(self, rhs: Self) -> Self::D;
345    /// Widening multiplication. This cannot overflow.
346    fn widen_mul(self, rhs: Self) -> Self::D;
347}
348
349macro_rules! impl_d_int {
350    ($($X:ident $D:ident),*) => {
351        $(
352            impl DInt for $D {
353                type H = $X;
354
355                fn lo(self) -> Self::H {
356                    self as $X
357                }
358                fn hi(self) -> Self::H {
359                    (self >> <$X as MinInt>::BITS) as $X
360                }
361            }
362        )*
363    };
364}
365
366macro_rules! impl_h_int {
367    ($($H:ident $uH:ident $X:ident),*) => {
368        $(
369            impl HInt for $H {
370                type D = $X;
371
372                fn widen(self) -> Self::D {
373                    self as $X
374                }
375                fn zero_widen(self) -> Self::D {
376                    (self as $uH) as $X
377                }
378                fn zero_widen_mul(self, rhs: Self) -> Self::D {
379                    self.zero_widen().wrapping_mul(rhs.zero_widen())
380                }
381                fn widen_mul(self, rhs: Self) -> Self::D {
382                    self.widen().wrapping_mul(rhs.widen())
383                }
384                fn widen_hi(self) -> Self::D {
385                    (self as $X) << <Self as MinInt>::BITS
386                }
387            }
388        )*
389    };
390}
391
392impl DInt for i128 {
    type H = i64;
    fn lo(self) -> Self::H { self as i64 }
    fn hi(self) -> Self::H { (self >> <i64 as MinInt>::BITS) as i64 }
}impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
393impl HInt for i64 {
    type D = i128;
    fn widen(self) -> Self::D { self as i128 }
    fn zero_widen(self) -> Self::D { (self as u64) as i128 }
    fn zero_widen_mul(self, rhs: Self) -> Self::D {
        self.zero_widen().wrapping_mul(rhs.zero_widen())
    }
    fn widen_mul(self, rhs: Self) -> Self::D {
        self.widen().wrapping_mul(rhs.widen())
    }
    fn widen_hi(self) -> Self::D { (self as i128) << <Self as MinInt>::BITS }
}impl_h_int!(
394    u8 u8 u16,
395    u16 u16 u32,
396    u32 u32 u64,
397    u64 u64 u128,
398    i8 u8 i16,
399    i16 u16 i32,
400    i32 u32 i64,
401    i64 u64 i128
402);
403
404/// Trait to express (possibly lossy) casting of integers
405pub trait CastInto<T: Copy>: Copy {
406    /// By default, casts should be exact.
407    #[track_caller]
408    fn cast(self) -> T;
409
410    /// Call for casts that are expected to truncate.
411    ///
412    /// In practice, this is exactly the same as `cast`; the main difference is to document intent
413    /// in code. `cast` may panic in debug mode.
414    fn cast_lossy(self) -> T;
415}
416
417pub trait CastFrom<T: Copy>: Copy {
418    /// By default, casts should be exact.
419    #[track_caller]
420    fn cast_from(value: T) -> Self;
421
422    /// Call for casts that are expected to truncate.
423    fn cast_from_lossy(value: T) -> Self;
424}
425
426impl<T: Copy, U: CastInto<T> + Copy> CastFrom<U> for T {
427    fn cast_from(value: U) -> Self {
428        value.cast()
429    }
430
431    fn cast_from_lossy(value: U) -> Self {
432        value.cast_lossy()
433    }
434}
435
436macro_rules! cast_into {
437    ($ty:ty) => {
438        cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128);
439    };
440    ($ty:ty; $($into:ty),*) => {$(
441        impl CastInto<$into> for $ty {
442            fn cast(self) -> $into {
443                // All we can really do to enforce casting rules is check the rules when in
444                // debug mode.
445                #[cfg(not(feature = "compiler-builtins"))]
446                debug_assert!(<$into>::try_from(self).is_ok(), "failed cast from {self}");
447                self as $into
448            }
449
450            fn cast_lossy(self) -> $into {
451                self as $into
452            }
453        }
454    )*};
455}
456
457macro_rules! cast_into_float {
458    ($ty:ty) => {
459        #[cfg(f16_enabled)]
460        cast_into_float!($ty; f16);
461
462        cast_into_float!($ty; f32, f64);
463
464        #[cfg(f128_enabled)]
465        cast_into_float!($ty; f128);
466    };
467    ($ty:ty; $($into:ty),*) => {$(
468        impl CastInto<$into> for $ty {
469            fn cast(self) -> $into {
470                #[cfg(not(feature = "compiler-builtins"))]
471                debug_assert_eq!(self as $into as $ty, self, "inexact float cast");
472                self as $into
473            }
474
475            fn cast_lossy(self) -> $into {
476                self as $into
477            }
478        }
479    )*};
480}
481
482impl CastInto<i128> for usize {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(usize);
483impl CastInto<i128> for isize {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(isize);
484impl CastInto<i128> for u8 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(u8);
485impl CastInto<i128> for i8 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(i8);
486impl CastInto<i128> for u16 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(u16);
487impl CastInto<i128> for i16 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(i16);
488impl CastInto<i128> for u32 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(u32);
489impl CastInto<i128> for i32 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(i32);
490impl CastInto<i128> for u64 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(u64);
491impl CastInto<i128> for i64 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(i64);
492impl CastInto<i128> for u128 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(u128);
493impl CastInto<i128> for i128 {
    fn cast(self) -> i128 {
        if true {
            if !<i128>::try_from(self).is_ok() {
                {
                    ::core::panicking::panic_fmt(format_args!("failed cast from {0}",
                            self));
                }
            };
        };
        self as i128
    }
    fn cast_lossy(self) -> i128 { self as i128 }
}cast_into!(i128);
494
495impl CastInto<f64> for i8 {
    fn cast(self) -> f64 {
        if true {
            match (&(self as f64 as i8), &self) {
                (left_val, right_val) => {
                    if !(*left_val == *right_val) {
                        let kind = ::core::panicking::AssertKind::Eq;
                        ::core::panicking::assert_failed(kind, &*left_val,
                            &*right_val,
                            ::core::option::Option::Some(format_args!("inexact float cast")));
                    }
                }
            };
        };
        self as f64
    }
    fn cast_lossy(self) -> f64 { self as f64 }
}cast_into_float!(i8);
496impl CastInto<f64> for i16 {
    fn cast(self) -> f64 {
        if true {
            match (&(self as f64 as i16), &self) {
                (left_val, right_val) => {
                    if !(*left_val == *right_val) {
                        let kind = ::core::panicking::AssertKind::Eq;
                        ::core::panicking::assert_failed(kind, &*left_val,
                            &*right_val,
                            ::core::option::Option::Some(format_args!("inexact float cast")));
                    }
                }
            };
        };
        self as f64
    }
    fn cast_lossy(self) -> f64 { self as f64 }
}cast_into_float!(i16);
497impl CastInto<f64> for i32 {
    fn cast(self) -> f64 {
        if true {
            match (&(self as f64 as i32), &self) {
                (left_val, right_val) => {
                    if !(*left_val == *right_val) {
                        let kind = ::core::panicking::AssertKind::Eq;
                        ::core::panicking::assert_failed(kind, &*left_val,
                            &*right_val,
                            ::core::option::Option::Some(format_args!("inexact float cast")));
                    }
                }
            };
        };
        self as f64
    }
    fn cast_lossy(self) -> f64 { self as f64 }
}cast_into_float!(i32);
498impl CastInto<f64> for i64 {
    fn cast(self) -> f64 {
        if true {
            match (&(self as f64 as i64), &self) {
                (left_val, right_val) => {
                    if !(*left_val == *right_val) {
                        let kind = ::core::panicking::AssertKind::Eq;
                        ::core::panicking::assert_failed(kind, &*left_val,
                            &*right_val,
                            ::core::option::Option::Some(format_args!("inexact float cast")));
                    }
                }
            };
        };
        self as f64
    }
    fn cast_lossy(self) -> f64 { self as f64 }
}cast_into_float!(i64);
499impl CastInto<f64> for i128 {
    fn cast(self) -> f64 {
        if true {
            match (&(self as f64 as i128), &self) {
                (left_val, right_val) => {
                    if !(*left_val == *right_val) {
                        let kind = ::core::panicking::AssertKind::Eq;
                        ::core::panicking::assert_failed(kind, &*left_val,
                            &*right_val,
                            ::core::option::Option::Some(format_args!("inexact float cast")));
                    }
                }
            };
        };
        self as f64
    }
    fn cast_lossy(self) -> f64 { self as f64 }
}cast_into_float!(i128);