nam_num_traits/ops/
checked.rs

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