num_traits/ops/
checked.rs

1use core::ops::{Add, Div, Mul, Rem, Shl, Shr, Sub};
2
3/// Performs addition that returns `None` instead of wrapping around on
4/// overflow.
5pub trait CheckedAdd: Sized + Add<Self, Output = Self> {
6    /// Adds two numbers, checking for overflow. If overflow happens, `None` is
7    /// returned.
8    fn checked_add(&self, v: &Self) -> Option<Self>;
9}
10
11macro_rules! checked_impl {
12    ($trait_name:ident, $method:ident, $t:ty) => {
13        impl $trait_name for $t {
14            #[inline]
15            fn $method(&self, v: &$t) -> Option<$t> {
16                <$t>::$method(*self, *v)
17            }
18        }
19    };
20}
21
22checked_impl!(CheckedAdd, checked_add, u8);
23checked_impl!(CheckedAdd, checked_add, u16);
24checked_impl!(CheckedAdd, checked_add, u32);
25checked_impl!(CheckedAdd, checked_add, u64);
26checked_impl!(CheckedAdd, checked_add, usize);
27#[cfg(has_i128)]
28checked_impl!(CheckedAdd, checked_add, u128);
29
30checked_impl!(CheckedAdd, checked_add, i8);
31checked_impl!(CheckedAdd, checked_add, i16);
32checked_impl!(CheckedAdd, checked_add, i32);
33checked_impl!(CheckedAdd, checked_add, i64);
34checked_impl!(CheckedAdd, checked_add, isize);
35#[cfg(has_i128)]
36checked_impl!(CheckedAdd, checked_add, i128);
37
38/// Performs subtraction that returns `None` instead of wrapping around on underflow.
39pub trait CheckedSub: Sized + Sub<Self, Output = Self> {
40    /// Subtracts two numbers, checking for underflow. If underflow happens,
41    /// `None` is returned.
42    fn checked_sub(&self, v: &Self) -> Option<Self>;
43}
44
45checked_impl!(CheckedSub, checked_sub, u8);
46checked_impl!(CheckedSub, checked_sub, u16);
47checked_impl!(CheckedSub, checked_sub, u32);
48checked_impl!(CheckedSub, checked_sub, u64);
49checked_impl!(CheckedSub, checked_sub, usize);
50#[cfg(has_i128)]
51checked_impl!(CheckedSub, checked_sub, u128);
52
53checked_impl!(CheckedSub, checked_sub, i8);
54checked_impl!(CheckedSub, checked_sub, i16);
55checked_impl!(CheckedSub, checked_sub, i32);
56checked_impl!(CheckedSub, checked_sub, i64);
57checked_impl!(CheckedSub, checked_sub, isize);
58#[cfg(has_i128)]
59checked_impl!(CheckedSub, checked_sub, i128);
60
61/// Performs multiplication that returns `None` instead of wrapping around on underflow or
62/// overflow.
63pub trait CheckedMul: Sized + Mul<Self, Output = Self> {
64    /// Multiplies two numbers, checking for underflow or overflow. If underflow
65    /// or overflow happens, `None` is returned.
66    fn checked_mul(&self, v: &Self) -> Option<Self>;
67}
68
69checked_impl!(CheckedMul, checked_mul, u8);
70checked_impl!(CheckedMul, checked_mul, u16);
71checked_impl!(CheckedMul, checked_mul, u32);
72checked_impl!(CheckedMul, checked_mul, u64);
73checked_impl!(CheckedMul, checked_mul, usize);
74#[cfg(has_i128)]
75checked_impl!(CheckedMul, checked_mul, u128);
76
77checked_impl!(CheckedMul, checked_mul, i8);
78checked_impl!(CheckedMul, checked_mul, i16);
79checked_impl!(CheckedMul, checked_mul, i32);
80checked_impl!(CheckedMul, checked_mul, i64);
81checked_impl!(CheckedMul, checked_mul, isize);
82#[cfg(has_i128)]
83checked_impl!(CheckedMul, checked_mul, i128);
84
85/// Performs division that returns `None` instead of panicking on division by zero and instead of
86/// wrapping around on underflow and overflow.
87pub trait CheckedDiv: Sized + Div<Self, Output = Self> {
88    /// Divides two numbers, checking for underflow, overflow and division by
89    /// zero. If any of that happens, `None` is returned.
90    fn checked_div(&self, v: &Self) -> Option<Self>;
91}
92
93checked_impl!(CheckedDiv, checked_div, u8);
94checked_impl!(CheckedDiv, checked_div, u16);
95checked_impl!(CheckedDiv, checked_div, u32);
96checked_impl!(CheckedDiv, checked_div, u64);
97checked_impl!(CheckedDiv, checked_div, usize);
98#[cfg(has_i128)]
99checked_impl!(CheckedDiv, checked_div, u128);
100
101checked_impl!(CheckedDiv, checked_div, i8);
102checked_impl!(CheckedDiv, checked_div, i16);
103checked_impl!(CheckedDiv, checked_div, i32);
104checked_impl!(CheckedDiv, checked_div, i64);
105checked_impl!(CheckedDiv, checked_div, isize);
106#[cfg(has_i128)]
107checked_impl!(CheckedDiv, checked_div, i128);
108
109/// Performs an integral remainder that returns `None` instead of panicking on division by zero and
110/// instead of wrapping around on underflow and overflow.
111pub trait CheckedRem: Sized + Rem<Self, Output = Self> {
112    /// Finds the remainder of dividing two numbers, checking for underflow, overflow and division
113    /// by zero. If any of that happens, `None` is returned.
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use num_traits::CheckedRem;
119    /// use std::i32::MIN;
120    ///
121    /// assert_eq!(CheckedRem::checked_rem(&10, &7), Some(3));
122    /// assert_eq!(CheckedRem::checked_rem(&10, &-7), Some(3));
123    /// assert_eq!(CheckedRem::checked_rem(&-10, &7), Some(-3));
124    /// assert_eq!(CheckedRem::checked_rem(&-10, &-7), Some(-3));
125    ///
126    /// assert_eq!(CheckedRem::checked_rem(&10, &0), None);
127    ///
128    /// assert_eq!(CheckedRem::checked_rem(&MIN, &1), Some(0));
129    /// assert_eq!(CheckedRem::checked_rem(&MIN, &-1), None);
130    /// ```
131    fn checked_rem(&self, v: &Self) -> Option<Self>;
132}
133
134checked_impl!(CheckedRem, checked_rem, u8);
135checked_impl!(CheckedRem, checked_rem, u16);
136checked_impl!(CheckedRem, checked_rem, u32);
137checked_impl!(CheckedRem, checked_rem, u64);
138checked_impl!(CheckedRem, checked_rem, usize);
139#[cfg(has_i128)]
140checked_impl!(CheckedRem, checked_rem, u128);
141
142checked_impl!(CheckedRem, checked_rem, i8);
143checked_impl!(CheckedRem, checked_rem, i16);
144checked_impl!(CheckedRem, checked_rem, i32);
145checked_impl!(CheckedRem, checked_rem, i64);
146checked_impl!(CheckedRem, checked_rem, isize);
147#[cfg(has_i128)]
148checked_impl!(CheckedRem, checked_rem, i128);
149
150macro_rules! checked_impl_unary {
151    ($trait_name:ident, $method:ident, $t:ty) => {
152        impl $trait_name for $t {
153            #[inline]
154            fn $method(&self) -> Option<$t> {
155                <$t>::$method(*self)
156            }
157        }
158    };
159}
160
161/// Performs negation that returns `None` if the result can't be represented.
162pub trait CheckedNeg: Sized {
163    /// Negates a number, returning `None` for results that can't be represented, like signed `MIN`
164    /// values that can't be positive, or non-zero unsigned values that can't be negative.
165    ///
166    /// # Examples
167    ///
168    /// ```
169    /// use num_traits::CheckedNeg;
170    /// use std::i32::MIN;
171    ///
172    /// assert_eq!(CheckedNeg::checked_neg(&1_i32), Some(-1));
173    /// assert_eq!(CheckedNeg::checked_neg(&-1_i32), Some(1));
174    /// assert_eq!(CheckedNeg::checked_neg(&MIN), None);
175    ///
176    /// assert_eq!(CheckedNeg::checked_neg(&0_u32), Some(0));
177    /// assert_eq!(CheckedNeg::checked_neg(&1_u32), None);
178    /// ```
179    fn checked_neg(&self) -> Option<Self>;
180}
181
182checked_impl_unary!(CheckedNeg, checked_neg, u8);
183checked_impl_unary!(CheckedNeg, checked_neg, u16);
184checked_impl_unary!(CheckedNeg, checked_neg, u32);
185checked_impl_unary!(CheckedNeg, checked_neg, u64);
186checked_impl_unary!(CheckedNeg, checked_neg, usize);
187#[cfg(has_i128)]
188checked_impl_unary!(CheckedNeg, checked_neg, u128);
189
190checked_impl_unary!(CheckedNeg, checked_neg, i8);
191checked_impl_unary!(CheckedNeg, checked_neg, i16);
192checked_impl_unary!(CheckedNeg, checked_neg, i32);
193checked_impl_unary!(CheckedNeg, checked_neg, i64);
194checked_impl_unary!(CheckedNeg, checked_neg, isize);
195#[cfg(has_i128)]
196checked_impl_unary!(CheckedNeg, checked_neg, i128);
197
198/// Performs a left shift that returns `None` on shifts larger than
199/// the type width.
200pub trait CheckedShl: Sized + Shl<u32, Output = Self> {
201    /// Checked shift left. Computes `self << rhs`, returning `None`
202    /// if `rhs` is larger than or equal to the number of bits in `self`.
203    ///
204    /// ```
205    /// use num_traits::CheckedShl;
206    ///
207    /// let x: u16 = 0x0001;
208    ///
209    /// assert_eq!(CheckedShl::checked_shl(&x, 0),  Some(0x0001));
210    /// assert_eq!(CheckedShl::checked_shl(&x, 1),  Some(0x0002));
211    /// assert_eq!(CheckedShl::checked_shl(&x, 15), Some(0x8000));
212    /// assert_eq!(CheckedShl::checked_shl(&x, 16), None);
213    /// ```
214    fn checked_shl(&self, rhs: u32) -> Option<Self>;
215}
216
217macro_rules! checked_shift_impl {
218    ($trait_name:ident, $method:ident, $t:ty) => {
219        impl $trait_name for $t {
220            #[inline]
221            fn $method(&self, rhs: u32) -> Option<$t> {
222                <$t>::$method(*self, rhs)
223            }
224        }
225    };
226}
227
228checked_shift_impl!(CheckedShl, checked_shl, u8);
229checked_shift_impl!(CheckedShl, checked_shl, u16);
230checked_shift_impl!(CheckedShl, checked_shl, u32);
231checked_shift_impl!(CheckedShl, checked_shl, u64);
232checked_shift_impl!(CheckedShl, checked_shl, usize);
233#[cfg(has_i128)]
234checked_shift_impl!(CheckedShl, checked_shl, u128);
235
236checked_shift_impl!(CheckedShl, checked_shl, i8);
237checked_shift_impl!(CheckedShl, checked_shl, i16);
238checked_shift_impl!(CheckedShl, checked_shl, i32);
239checked_shift_impl!(CheckedShl, checked_shl, i64);
240checked_shift_impl!(CheckedShl, checked_shl, isize);
241#[cfg(has_i128)]
242checked_shift_impl!(CheckedShl, checked_shl, i128);
243
244/// Performs a right shift that returns `None` on shifts larger than
245/// the type width.
246pub trait CheckedShr: Sized + Shr<u32, Output = Self> {
247    /// Checked shift right. Computes `self >> rhs`, returning `None`
248    /// if `rhs` is larger than or equal to the number of bits in `self`.
249    ///
250    /// ```
251    /// use num_traits::CheckedShr;
252    ///
253    /// let x: u16 = 0x8000;
254    ///
255    /// assert_eq!(CheckedShr::checked_shr(&x, 0),  Some(0x8000));
256    /// assert_eq!(CheckedShr::checked_shr(&x, 1),  Some(0x4000));
257    /// assert_eq!(CheckedShr::checked_shr(&x, 15), Some(0x0001));
258    /// assert_eq!(CheckedShr::checked_shr(&x, 16), None);
259    /// ```
260    fn checked_shr(&self, rhs: u32) -> Option<Self>;
261}
262
263checked_shift_impl!(CheckedShr, checked_shr, u8);
264checked_shift_impl!(CheckedShr, checked_shr, u16);
265checked_shift_impl!(CheckedShr, checked_shr, u32);
266checked_shift_impl!(CheckedShr, checked_shr, u64);
267checked_shift_impl!(CheckedShr, checked_shr, usize);
268#[cfg(has_i128)]
269checked_shift_impl!(CheckedShr, checked_shr, u128);
270
271checked_shift_impl!(CheckedShr, checked_shr, i8);
272checked_shift_impl!(CheckedShr, checked_shr, i16);
273checked_shift_impl!(CheckedShr, checked_shr, i32);
274checked_shift_impl!(CheckedShr, checked_shr, i64);
275checked_shift_impl!(CheckedShr, checked_shr, isize);
276#[cfg(has_i128)]
277checked_shift_impl!(CheckedShr, checked_shr, i128);