Skip to main content

core/num/
saturating.rs

1//! Definitions of `Saturating<T>`.
2
3use crate::fmt;
4use crate::ops::{
5    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
6    Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign,
7};
8
9/// Provides intentionally-saturating arithmetic on `T`.
10///
11/// Operations like `+` on `u32` values are intended to never overflow,
12/// and in some debug configurations overflow is detected and results
13/// in a panic. While most arithmetic falls into this category, some
14/// code explicitly expects and relies upon saturating arithmetic.
15///
16/// Saturating arithmetic can be achieved either through methods like
17/// `saturating_add`, or through the `Saturating<T>` type, which says that
18/// all standard arithmetic operations on the underlying value are
19/// intended to have saturating semantics.
20///
21/// The underlying value can be retrieved through the `.0` index of the
22/// `Saturating` tuple.
23///
24/// # Examples
25///
26/// ```
27/// use std::num::Saturating;
28///
29/// let max = Saturating(u32::MAX);
30/// let one = Saturating(1u32);
31///
32/// assert_eq!(u32::MAX, (max + one).0);
33/// ```
34#[stable(feature = "saturating_int_impl", since = "1.74.0")]
35#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
36#[repr(transparent)]
37#[rustc_diagnostic_item = "Saturating"]
38pub struct Saturating<T>(#[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T);
39
40#[stable(feature = "saturating_int_impl", since = "1.74.0")]
41impl<T: fmt::Debug> fmt::Debug for Saturating<T> {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        self.0.fmt(f)
44    }
45}
46
47#[stable(feature = "saturating_int_impl", since = "1.74.0")]
48impl<T: fmt::Display> fmt::Display for Saturating<T> {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        self.0.fmt(f)
51    }
52}
53
54#[stable(feature = "saturating_int_impl", since = "1.74.0")]
55impl<T: fmt::Binary> fmt::Binary for Saturating<T> {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        self.0.fmt(f)
58    }
59}
60
61#[stable(feature = "saturating_int_impl", since = "1.74.0")]
62impl<T: fmt::Octal> fmt::Octal for Saturating<T> {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        self.0.fmt(f)
65    }
66}
67
68#[stable(feature = "saturating_int_impl", since = "1.74.0")]
69impl<T: fmt::LowerHex> fmt::LowerHex for Saturating<T> {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        self.0.fmt(f)
72    }
73}
74
75#[stable(feature = "saturating_int_impl", since = "1.74.0")]
76impl<T: fmt::UpperHex> fmt::UpperHex for Saturating<T> {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        self.0.fmt(f)
79    }
80}
81
82// FIXME the correct implementation is not clear. Waiting for a real world use case at https://github.com/rust-lang/libs-team/issues/230
83//
84// #[allow(unused_macros)]
85// macro_rules! sh_impl_signed {
86//     ($t:ident, $f:ident) => {
87//         // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065
88//         //
89//         // #[unstable(feature = "saturating_int_impl", issue = "87920")]
90//         // impl Shl<$f> for Saturating<$t> {
91//         //     type Output = Saturating<$t>;
92//         //
93//         //     #[inline]
94//         //     fn shl(self, other: $f) -> Saturating<$t> {
95//         //         if other < 0 {
96//         //             Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32))
97//         //         } else {
98//         //             Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32))
99//         //         }
100//         //     }
101//         // }
102//         // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
103//         // #[unstable(feature = "saturating_int_impl", issue = "87920")] }
104//         //
105//         // #[unstable(feature = "saturating_int_impl", issue = "87920")]
106//         // impl ShlAssign<$f> for Saturating<$t> {
107//         //     #[inline]
108//         //     fn shl_assign(&mut self, other: $f) {
109//         //         *self = *self << other;
110//         //     }
111//         // }
112//         // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f,
113//         // #[unstable(feature = "saturating_int_impl", issue = "87920")] }
114//
115//         #[unstable(feature = "saturating_int_impl", issue = "87920")]
116//         impl Shr<$f> for Saturating<$t> {
117//             type Output = Saturating<$t>;
118//
119//             #[inline]
120//             fn shr(self, other: $f) -> Saturating<$t> {
121//                 if other < 0 {
122//                     Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32))
123//                 } else {
124//                     Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32))
125//                 }
126//             }
127//         }
128//         forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
129//         #[unstable(feature = "saturating_int_impl", issue = "87920")] }
130//
131//         #[unstable(feature = "saturating_int_impl", issue = "87920")]
132//         impl ShrAssign<$f> for Saturating<$t> {
133//             #[inline]
134//             fn shr_assign(&mut self, other: $f) {
135//                 *self = *self >> other;
136//             }
137//         }
138//         forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f,
139//         #[unstable(feature = "saturating_int_impl", issue = "87920")] }
140//     };
141// }
142//
143// macro_rules! sh_impl_unsigned {
144//     ($t:ident, $f:ident) => {
145//         #[unstable(feature = "saturating_int_impl", issue = "87920")]
146//         impl Shl<$f> for Saturating<$t> {
147//             type Output = Saturating<$t>;
148//
149//             #[inline]
150//             fn shl(self, other: $f) -> Saturating<$t> {
151//                 Saturating(self.0.wrapping_shl(other as u32))
152//             }
153//         }
154//         forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
155//         #[unstable(feature = "saturating_int_impl", issue = "87920")] }
156//
157//         #[unstable(feature = "saturating_int_impl", issue = "87920")]
158//         impl ShlAssign<$f> for Saturating<$t> {
159//             #[inline]
160//             fn shl_assign(&mut self, other: $f) {
161//                 *self = *self << other;
162//             }
163//         }
164//         forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f,
165//         #[unstable(feature = "saturating_int_impl", issue = "87920")] }
166//
167//         #[unstable(feature = "saturating_int_impl", issue = "87920")]
168//         impl Shr<$f> for Saturating<$t> {
169//             type Output = Saturating<$t>;
170//
171//             #[inline]
172//             fn shr(self, other: $f) -> Saturating<$t> {
173//                 Saturating(self.0.wrapping_shr(other as u32))
174//             }
175//         }
176//         forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
177//         #[unstable(feature = "saturating_int_impl", issue = "87920")] }
178//
179//         #[unstable(feature = "saturating_int_impl", issue = "87920")]
180//         impl ShrAssign<$f> for Saturating<$t> {
181//             #[inline]
182//             fn shr_assign(&mut self, other: $f) {
183//                 *self = *self >> other;
184//             }
185//         }
186//         forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f,
187//         #[unstable(feature = "saturating_int_impl", issue = "87920")] }
188//     };
189// }
190//
191// // FIXME (#23545): uncomment the remaining impls
192// macro_rules! sh_impl_all {
193//     ($($t:ident)*) => ($(
194//         //sh_impl_unsigned! { $t, u8 }
195//         //sh_impl_unsigned! { $t, u16 }
196//         //sh_impl_unsigned! { $t, u32 }
197//         //sh_impl_unsigned! { $t, u64 }
198//         //sh_impl_unsigned! { $t, u128 }
199//         sh_impl_unsigned! { $t, usize }
200//
201//         //sh_impl_signed! { $t, i8 }
202//         //sh_impl_signed! { $t, i16 }
203//         //sh_impl_signed! { $t, i32 }
204//         //sh_impl_signed! { $t, i64 }
205//         //sh_impl_signed! { $t, i128 }
206//         //sh_impl_signed! { $t, isize }
207//     )*)
208// }
209//
210// sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
211
212// FIXME(30524): impl Op<T> for Saturating<T>, impl OpAssign<T> for Saturating<T>
213macro_rules! saturating_impl {
214    ($($t:ty)*) => ($(
215        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
216        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
217        impl const Add for Saturating<$t> {
218            type Output = Saturating<$t>;
219
220            #[inline]
221            #[ferrocene::prevalidated]
222            fn add(self, other: Saturating<$t>) -> Saturating<$t> {
223                Saturating(self.0.saturating_add(other.0))
224            }
225        }
226        forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>,
227        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
228        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
229
230        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
231        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
232        impl const AddAssign for Saturating<$t> {
233            #[inline]
234            #[ferrocene::prevalidated]
235            fn add_assign(&mut self, other: Saturating<$t>) {
236                *self = *self + other;
237            }
238        }
239        forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t>,
240        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
241        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
242
243        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
244        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
245        impl const AddAssign<$t> for Saturating<$t> {
246            #[inline]
247            #[ferrocene::prevalidated]
248            fn add_assign(&mut self, other: $t) {
249                *self = *self + Saturating(other);
250            }
251        }
252        forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t,
253        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
254        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
255
256        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
257        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
258        impl const Sub for Saturating<$t> {
259            type Output = Saturating<$t>;
260
261            #[inline]
262            #[ferrocene::prevalidated]
263            fn sub(self, other: Saturating<$t>) -> Saturating<$t> {
264                Saturating(self.0.saturating_sub(other.0))
265            }
266        }
267        forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>,
268        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
269        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
270
271        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
272        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
273        impl const SubAssign for Saturating<$t> {
274            #[inline]
275            #[ferrocene::prevalidated]
276            fn sub_assign(&mut self, other: Saturating<$t>) {
277                *self = *self - other;
278            }
279        }
280        forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t>,
281        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
282        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
283
284        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
285        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
286        impl const SubAssign<$t> for Saturating<$t> {
287            #[inline]
288            #[ferrocene::prevalidated]
289            fn sub_assign(&mut self, other: $t) {
290                *self = *self - Saturating(other);
291            }
292        }
293        forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t,
294        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
295        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
296
297        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
298        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
299        impl const Mul for Saturating<$t> {
300            type Output = Saturating<$t>;
301
302            #[inline]
303            #[ferrocene::prevalidated]
304            fn mul(self, other: Saturating<$t>) -> Saturating<$t> {
305                Saturating(self.0.saturating_mul(other.0))
306            }
307        }
308        forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>,
309        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
310        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
311
312        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
313        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
314        impl const MulAssign for Saturating<$t> {
315            #[inline]
316            #[ferrocene::prevalidated]
317            fn mul_assign(&mut self, other: Saturating<$t>) {
318                *self = *self * other;
319            }
320        }
321        forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t>,
322        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
323        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
324
325        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
326        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
327        impl const MulAssign<$t> for Saturating<$t> {
328            #[inline]
329            #[ferrocene::prevalidated]
330            fn mul_assign(&mut self, other: $t) {
331                *self = *self * Saturating(other);
332            }
333        }
334        forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, $t,
335        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
336        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
337
338        /// # Examples
339        ///
340        /// ```
341        /// use std::num::Saturating;
342        ///
343        #[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")]
344        #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MAX), Saturating(", stringify!($t), "::MAX) / Saturating(1));")]
345        #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN), Saturating(", stringify!($t), "::MIN) / Saturating(1));")]
346        /// ```
347        ///
348        /// ```should_panic
349        /// use std::num::Saturating;
350        ///
351        #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")]
352        /// ```
353        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
354        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
355        impl const Div for Saturating<$t> {
356            type Output = Saturating<$t>;
357
358            #[inline]
359            #[ferrocene::prevalidated]
360            fn div(self, other: Saturating<$t>) -> Saturating<$t> {
361                Saturating(self.0.saturating_div(other.0))
362            }
363        }
364        forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>,
365        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
366        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
367
368        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
369        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
370        impl const DivAssign for Saturating<$t> {
371            #[inline]
372            #[ferrocene::prevalidated]
373            fn div_assign(&mut self, other: Saturating<$t>) {
374                *self = *self / other;
375            }
376        }
377        forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t>,
378        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
379        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
380
381        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
382        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
383        impl const DivAssign<$t> for Saturating<$t> {
384            #[inline]
385            #[ferrocene::prevalidated]
386            fn div_assign(&mut self, other: $t) {
387                *self = *self / Saturating(other);
388            }
389        }
390        forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t,
391        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
392        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
393
394        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
395        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
396        impl const Rem for Saturating<$t> {
397            type Output = Saturating<$t>;
398
399            #[inline]
400            #[ferrocene::prevalidated]
401            fn rem(self, other: Saturating<$t>) -> Saturating<$t> {
402                Saturating(self.0.rem(other.0))
403            }
404        }
405        forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>,
406        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
407        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
408
409        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
410        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
411        impl const RemAssign for Saturating<$t> {
412            #[inline]
413            #[ferrocene::prevalidated]
414            fn rem_assign(&mut self, other: Saturating<$t>) {
415                *self = *self % other;
416            }
417        }
418        forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t>,
419        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
420        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
421
422        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
423        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
424        impl const RemAssign<$t> for Saturating<$t> {
425            #[inline]
426            #[ferrocene::prevalidated]
427            fn rem_assign(&mut self, other: $t) {
428                *self = *self % Saturating(other);
429            }
430        }
431        forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t,
432        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
433        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
434
435        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
436        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
437        impl const Not for Saturating<$t> {
438            type Output = Saturating<$t>;
439
440            #[inline]
441            #[ferrocene::prevalidated]
442            fn not(self) -> Saturating<$t> {
443                Saturating(!self.0)
444            }
445        }
446        forward_ref_unop! { impl Not, not for Saturating<$t>,
447        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
448        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
449
450        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
451        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
452        impl const BitXor for Saturating<$t> {
453            type Output = Saturating<$t>;
454
455            #[inline]
456            #[ferrocene::prevalidated]
457            fn bitxor(self, other: Saturating<$t>) -> Saturating<$t> {
458                Saturating(self.0 ^ other.0)
459            }
460        }
461        forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>,
462        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
463        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
464
465        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
466        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
467        impl const BitXorAssign for Saturating<$t> {
468            #[inline]
469            #[ferrocene::prevalidated]
470            fn bitxor_assign(&mut self, other: Saturating<$t>) {
471                *self = *self ^ other;
472            }
473        }
474        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t>,
475        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
476        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
477
478        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
479        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
480        impl const BitXorAssign<$t> for Saturating<$t> {
481            #[inline]
482            #[ferrocene::prevalidated]
483            fn bitxor_assign(&mut self, other: $t) {
484                *self = *self ^ Saturating(other);
485            }
486        }
487        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t,
488        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
489        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
490
491        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
492        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
493        impl const BitOr for Saturating<$t> {
494            type Output = Saturating<$t>;
495
496            #[inline]
497            #[ferrocene::prevalidated]
498            fn bitor(self, other: Saturating<$t>) -> Saturating<$t> {
499                Saturating(self.0 | other.0)
500            }
501        }
502        forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>,
503        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
504        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
505
506        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
507        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
508        impl const BitOrAssign for Saturating<$t> {
509            #[inline]
510            #[ferrocene::prevalidated]
511            fn bitor_assign(&mut self, other: Saturating<$t>) {
512                *self = *self | other;
513            }
514        }
515        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t>,
516        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
517        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
518
519        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
520        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
521        impl const BitOrAssign<$t> for Saturating<$t> {
522            #[inline]
523            #[ferrocene::prevalidated]
524            fn bitor_assign(&mut self, other: $t) {
525                *self = *self | Saturating(other);
526            }
527        }
528        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t,
529        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
530        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
531
532        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
533        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
534        impl const BitAnd for Saturating<$t> {
535            type Output = Saturating<$t>;
536
537            #[inline]
538            #[ferrocene::prevalidated]
539            fn bitand(self, other: Saturating<$t>) -> Saturating<$t> {
540                Saturating(self.0 & other.0)
541            }
542        }
543        forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>,
544        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
545        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
546
547        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
548        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
549        impl const BitAndAssign for Saturating<$t> {
550            #[inline]
551            #[ferrocene::prevalidated]
552            fn bitand_assign(&mut self, other: Saturating<$t>) {
553                *self = *self & other;
554            }
555        }
556        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t>,
557        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
558        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
559
560        #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
561        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
562        impl const BitAndAssign<$t> for Saturating<$t> {
563            #[inline]
564            #[ferrocene::prevalidated]
565            fn bitand_assign(&mut self, other: $t) {
566                *self = *self & Saturating(other);
567            }
568        }
569        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, $t,
570        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
571        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
572
573    )*)
574}
575
576saturating_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
577
578macro_rules! saturating_int_impl {
579    ($($t:ty)*) => ($(
580        impl Saturating<$t> {
581            /// Returns the smallest value that can be represented by this integer type.
582            ///
583            /// # Examples
584            ///
585            /// ```
586            /// use std::num::Saturating;
587            ///
588            #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MIN, Saturating(", stringify!($t), "::MIN));")]
589            /// ```
590            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
591            pub const MIN: Self = Self(<$t>::MIN);
592
593            /// Returns the largest value that can be represented by this integer type.
594            ///
595            /// # Examples
596            ///
597            /// ```
598            /// use std::num::Saturating;
599            ///
600            #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MAX, Saturating(", stringify!($t), "::MAX));")]
601            /// ```
602            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
603            pub const MAX: Self = Self(<$t>::MAX);
604
605            /// Returns the size of this integer type in bits.
606            ///
607            /// # Examples
608            ///
609            /// ```
610            /// use std::num::Saturating;
611            ///
612            #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::BITS, ", stringify!($t), "::BITS);")]
613            /// ```
614            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
615            pub const BITS: u32 = <$t>::BITS;
616
617            /// Returns the number of ones in the binary representation of `self`.
618            ///
619            /// # Examples
620            ///
621            /// ```
622            /// use std::num::Saturating;
623            ///
624            #[doc = concat!("let n = Saturating(0b01001100", stringify!($t), ");")]
625            ///
626            /// assert_eq!(n.count_ones(), 3);
627            /// ```
628            #[inline]
629            #[doc(alias = "popcount")]
630            #[doc(alias = "popcnt")]
631            #[must_use = "this returns the result of the operation, \
632                          without modifying the original"]
633            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
634            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
635            pub const fn count_ones(self) -> u32 {
636                self.0.count_ones()
637            }
638
639            /// Returns the number of zeros in the binary representation of `self`.
640            ///
641            /// # Examples
642            ///
643            /// ```
644            /// use std::num::Saturating;
645            ///
646            #[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")]
647            /// ```
648            #[inline]
649            #[must_use = "this returns the result of the operation, \
650                          without modifying the original"]
651            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
652            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
653            pub const fn count_zeros(self) -> u32 {
654                self.0.count_zeros()
655            }
656
657            /// Returns the number of trailing zeros in the binary representation of `self`.
658            ///
659            /// # Examples
660            ///
661            /// ```
662            /// use std::num::Saturating;
663            ///
664            #[doc = concat!("let n = Saturating(0b0101000", stringify!($t), ");")]
665            ///
666            /// assert_eq!(n.trailing_zeros(), 3);
667            /// ```
668            #[inline]
669            #[must_use = "this returns the result of the operation, \
670                          without modifying the original"]
671            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
672            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
673            pub const fn trailing_zeros(self) -> u32 {
674                self.0.trailing_zeros()
675            }
676
677            /// Shifts the bits to the left by a specified amount, `n`,
678            /// saturating the truncated bits to the end of the resulting
679            /// integer.
680            ///
681            /// Please note this isn't the same operation as the `<<` shifting
682            /// operator!
683            ///
684            /// # Examples
685            ///
686            /// ```
687            /// use std::num::Saturating;
688            ///
689            /// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
690            /// let m: Saturating<i64> = Saturating(-0x76543210FEDCBA99);
691            ///
692            /// assert_eq!(n.rotate_left(32), m);
693            /// ```
694            #[inline]
695            #[must_use = "this returns the result of the operation, \
696                          without modifying the original"]
697            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
698            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
699            pub const fn rotate_left(self, n: u32) -> Self {
700                Saturating(self.0.rotate_left(n))
701            }
702
703            /// Shifts the bits to the right by a specified amount, `n`,
704            /// saturating the truncated bits to the beginning of the resulting
705            /// integer.
706            ///
707            /// Please note this isn't the same operation as the `>>` shifting
708            /// operator!
709            ///
710            /// # Examples
711            ///
712            /// ```
713            /// use std::num::Saturating;
714            ///
715            /// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
716            /// let m: Saturating<i64> = Saturating(-0xFEDCBA987654322);
717            ///
718            /// assert_eq!(n.rotate_right(4), m);
719            /// ```
720            #[inline]
721            #[must_use = "this returns the result of the operation, \
722                          without modifying the original"]
723            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
724            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
725            pub const fn rotate_right(self, n: u32) -> Self {
726                Saturating(self.0.rotate_right(n))
727            }
728
729            /// Reverses the byte order of the integer.
730            ///
731            /// # Examples
732            ///
733            /// ```
734            /// use std::num::Saturating;
735            ///
736            /// let n: Saturating<i16> = Saturating(0b0000000_01010101);
737            /// assert_eq!(n, Saturating(85));
738            ///
739            /// let m = n.swap_bytes();
740            ///
741            /// assert_eq!(m, Saturating(0b01010101_00000000));
742            /// assert_eq!(m, Saturating(21760));
743            /// ```
744            #[inline]
745            #[must_use = "this returns the result of the operation, \
746                          without modifying the original"]
747            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
748            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
749            pub const fn swap_bytes(self) -> Self {
750                Saturating(self.0.swap_bytes())
751            }
752
753            /// Reverses the bit pattern of the integer.
754            ///
755            /// # Examples
756            ///
757            /// Please note that this example is shared among integer types, which is why `i16`
758            /// is used.
759            ///
760            /// ```
761            /// use std::num::Saturating;
762            ///
763            /// let n = Saturating(0b0000000_01010101i16);
764            /// assert_eq!(n, Saturating(85));
765            ///
766            /// let m = n.reverse_bits();
767            ///
768            /// assert_eq!(m.0 as u16, 0b10101010_00000000);
769            /// assert_eq!(m, Saturating(-22016));
770            /// ```
771            #[inline]
772            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
773            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
774            #[must_use = "this returns the result of the operation, \
775                          without modifying the original"]
776            pub const fn reverse_bits(self) -> Self {
777                Saturating(self.0.reverse_bits())
778            }
779
780            /// Converts an integer from big endian to the target's endianness.
781            ///
782            /// On big endian this is a no-op. On little endian the bytes are
783            /// swapped.
784            ///
785            /// # Examples
786            ///
787            /// ```
788            /// use std::num::Saturating;
789            ///
790            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
791            ///
792            /// if cfg!(target_endian = "big") {
793            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_be(n), n)")]
794            /// } else {
795            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_be(n), n.swap_bytes())")]
796            /// }
797            /// ```
798            #[inline]
799            #[must_use]
800            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
801            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
802            pub const fn from_be(x: Self) -> Self {
803                Saturating(<$t>::from_be(x.0))
804            }
805
806            /// Converts an integer from little endian to the target's endianness.
807            ///
808            /// On little endian this is a no-op. On big endian the bytes are
809            /// swapped.
810            ///
811            /// # Examples
812            ///
813            /// ```
814            /// use std::num::Saturating;
815            ///
816            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
817            ///
818            /// if cfg!(target_endian = "little") {
819            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_le(n), n)")]
820            /// } else {
821            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_le(n), n.swap_bytes())")]
822            /// }
823            /// ```
824            #[inline]
825            #[must_use]
826            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
827            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
828            pub const fn from_le(x: Self) -> Self {
829                Saturating(<$t>::from_le(x.0))
830            }
831
832            /// Converts `self` to big endian from the target's endianness.
833            ///
834            /// On big endian this is a no-op. On little endian the bytes are
835            /// swapped.
836            ///
837            /// # Examples
838            ///
839            /// ```
840            /// use std::num::Saturating;
841            ///
842            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
843            ///
844            /// if cfg!(target_endian = "big") {
845            ///     assert_eq!(n.to_be(), n)
846            /// } else {
847            ///     assert_eq!(n.to_be(), n.swap_bytes())
848            /// }
849            /// ```
850            #[inline]
851            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
852            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
853            #[must_use = "this returns the result of the operation, \
854                          without modifying the original"]
855            pub const fn to_be(self) -> Self {
856                Saturating(self.0.to_be())
857            }
858
859            /// Converts `self` to little endian from the target's endianness.
860            ///
861            /// On little endian this is a no-op. On big endian the bytes are
862            /// swapped.
863            ///
864            /// # Examples
865            ///
866            /// ```
867            /// use std::num::Saturating;
868            ///
869            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
870            ///
871            /// if cfg!(target_endian = "little") {
872            ///     assert_eq!(n.to_le(), n)
873            /// } else {
874            ///     assert_eq!(n.to_le(), n.swap_bytes())
875            /// }
876            /// ```
877            #[inline]
878            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
879            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
880            #[must_use = "this returns the result of the operation, \
881                          without modifying the original"]
882            pub const fn to_le(self) -> Self {
883                Saturating(self.0.to_le())
884            }
885
886            /// Raises self to the power of `exp`, using exponentiation by squaring.
887            ///
888            /// # Examples
889            ///
890            /// ```
891            /// use std::num::Saturating;
892            ///
893            #[doc = concat!("assert_eq!(Saturating(3", stringify!($t), ").pow(4), Saturating(81));")]
894            /// ```
895            ///
896            /// Results that are too large are saturated:
897            ///
898            /// ```
899            /// use std::num::Saturating;
900            ///
901            /// assert_eq!(Saturating(3i8).pow(5), Saturating(127));
902            /// assert_eq!(Saturating(3i8).pow(6), Saturating(127));
903            /// ```
904            #[inline]
905            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
906            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
907            #[must_use = "this returns the result of the operation, \
908                          without modifying the original"]
909            pub const fn pow(self, exp: u32) -> Self {
910                Saturating(self.0.saturating_pow(exp))
911            }
912        }
913    )*)
914}
915
916saturating_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
917
918macro_rules! saturating_int_impl_signed {
919    ($($t:ty)*) => ($(
920        impl Saturating<$t> {
921            /// Returns the number of leading zeros in the binary representation of `self`.
922            ///
923            /// # Examples
924            ///
925            /// ```
926            /// use std::num::Saturating;
927            ///
928            #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
929            ///
930            /// assert_eq!(n.leading_zeros(), 3);
931            /// ```
932            #[inline]
933            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
934            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
935            #[must_use = "this returns the result of the operation, \
936                          without modifying the original"]
937            pub const fn leading_zeros(self) -> u32 {
938                self.0.leading_zeros()
939            }
940
941            /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == MIN`
942            /// instead of overflowing.
943            ///
944            /// # Examples
945            ///
946            /// ```
947            /// use std::num::Saturating;
948            ///
949            #[doc = concat!("assert_eq!(Saturating(100", stringify!($t), ").abs(), Saturating(100));")]
950            #[doc = concat!("assert_eq!(Saturating(-100", stringify!($t), ").abs(), Saturating(100));")]
951            #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating((", stringify!($t), "::MIN + 1).abs()));")]
952            #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MIN.saturating_abs()));")]
953            #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MAX));")]
954            /// ```
955            #[inline]
956            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
957            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
958            #[must_use = "this returns the result of the operation, \
959                          without modifying the original"]
960            pub const fn abs(self) -> Saturating<$t> {
961                Saturating(self.0.saturating_abs())
962            }
963
964            /// Returns a number representing sign of `self`.
965            ///
966            ///  - `0` if the number is zero
967            ///  - `1` if the number is positive
968            ///  - `-1` if the number is negative
969            ///
970            /// # Examples
971            ///
972            /// ```
973            /// use std::num::Saturating;
974            ///
975            #[doc = concat!("assert_eq!(Saturating(10", stringify!($t), ").signum(), Saturating(1));")]
976            #[doc = concat!("assert_eq!(Saturating(0", stringify!($t), ").signum(), Saturating(0));")]
977            #[doc = concat!("assert_eq!(Saturating(-10", stringify!($t), ").signum(), Saturating(-1));")]
978            /// ```
979            #[inline]
980            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
981            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
982            #[must_use = "this returns the result of the operation, \
983                          without modifying the original"]
984            pub const fn signum(self) -> Saturating<$t> {
985                Saturating(self.0.signum())
986            }
987
988            /// Returns `true` if `self` is positive and `false` if the number is zero or
989            /// negative.
990            ///
991            /// # Examples
992            ///
993            /// ```
994            /// use std::num::Saturating;
995            ///
996            #[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")]
997            #[doc = concat!("assert!(!Saturating(-10", stringify!($t), ").is_positive());")]
998            /// ```
999            #[must_use]
1000            #[inline]
1001            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
1002            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
1003            pub const fn is_positive(self) -> bool {
1004                self.0.is_positive()
1005            }
1006
1007            /// Returns `true` if `self` is negative and `false` if the number is zero or
1008            /// positive.
1009            ///
1010            /// # Examples
1011            ///
1012            /// ```
1013            /// use std::num::Saturating;
1014            ///
1015            #[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")]
1016            #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_negative());")]
1017            /// ```
1018            #[must_use]
1019            #[inline]
1020            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
1021            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
1022            pub const fn is_negative(self) -> bool {
1023                self.0.is_negative()
1024            }
1025        }
1026
1027        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
1028        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1029        impl const Neg for Saturating<$t> {
1030            type Output = Self;
1031            #[inline]
1032            #[ferrocene::prevalidated]
1033            fn neg(self) -> Self {
1034                Saturating(self.0.saturating_neg())
1035            }
1036        }
1037        forward_ref_unop! { impl Neg, neg for Saturating<$t>,
1038        #[stable(feature = "saturating_int_impl", since = "1.74.0")]
1039        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
1040    )*)
1041}
1042
1043saturating_int_impl_signed! { isize i8 i16 i32 i64 i128 }
1044
1045macro_rules! saturating_int_impl_unsigned {
1046    ($($t:ty)*) => ($(
1047        impl Saturating<$t> {
1048            /// Returns the number of leading zeros in the binary representation of `self`.
1049            ///
1050            /// # Examples
1051            ///
1052            /// ```
1053            /// use std::num::Saturating;
1054            ///
1055            #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
1056            ///
1057            /// assert_eq!(n.leading_zeros(), 2);
1058            /// ```
1059            #[inline]
1060            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
1061            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
1062            #[must_use = "this returns the result of the operation, \
1063                          without modifying the original"]
1064            pub const fn leading_zeros(self) -> u32 {
1065                self.0.leading_zeros()
1066            }
1067
1068            /// Returns `true` if and only if `self == 2^k` for some `k`.
1069            ///
1070            /// # Examples
1071            ///
1072            /// ```
1073            /// use std::num::Saturating;
1074            ///
1075            #[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")]
1076            #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_power_of_two());")]
1077            /// ```
1078            #[must_use]
1079            #[inline]
1080            #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
1081            #[stable(feature = "saturating_int_impl", since = "1.74.0")]
1082            pub const fn is_power_of_two(self) -> bool {
1083                self.0.is_power_of_two()
1084            }
1085
1086        }
1087    )*)
1088}
1089
1090saturating_int_impl_unsigned! { usize u8 u16 u32 u64 u128 }
1091
1092// Related to potential Shl and ShlAssign implementation
1093//
1094// mod shift_max {
1095//     #![allow(non_upper_case_globals)]
1096//
1097//     #[cfg(target_pointer_width = "16")]
1098//     mod platform {
1099//         pub const usize: u32 = super::u16;
1100//         pub const isize: u32 = super::i16;
1101//     }
1102//
1103//     #[cfg(target_pointer_width = "32")]
1104//     mod platform {
1105//         pub const usize: u32 = super::u32;
1106//         pub const isize: u32 = super::i32;
1107//     }
1108//
1109//     #[cfg(target_pointer_width = "64")]
1110//     mod platform {
1111//         pub const usize: u32 = super::u64;
1112//         pub const isize: u32 = super::i64;
1113//     }
1114//
1115//     pub const i8: u32 = (1 << 3) - 1;
1116//     pub const i16: u32 = (1 << 4) - 1;
1117//     pub const i32: u32 = (1 << 5) - 1;
1118//     pub const i64: u32 = (1 << 6) - 1;
1119//     pub const i128: u32 = (1 << 7) - 1;
1120//     pub use self::platform::isize;
1121//
1122//     pub const u8: u32 = i8;
1123//     pub const u16: u32 = i16;
1124//     pub const u32: u32 = i32;
1125//     pub const u64: u32 = i64;
1126//     pub const u128: u32 = i128;
1127//     pub use self::platform::usize;
1128// }