1 use core::ops::{Add, Div, Mul, Rem, Shl, Shr, Sub};
2 
3 /// Performs addition that returns `None` instead of wrapping around on
4 /// overflow.
5 pub trait CheckedAdd: Sized + Add<Self, Output = Self> {
6     /// Adds two numbers, checking for overflow. If overflow happens, `None` is
7     /// returned.
checked_add(&self, v: &Self) -> Option<Self>8     fn checked_add(&self, v: &Self) -> Option<Self>;
9 }
10 
11 macro_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 
22 checked_impl!(CheckedAdd, checked_add, u8);
23 checked_impl!(CheckedAdd, checked_add, u16);
24 checked_impl!(CheckedAdd, checked_add, u32);
25 checked_impl!(CheckedAdd, checked_add, u64);
26 checked_impl!(CheckedAdd, checked_add, usize);
27 #[cfg(has_i128)]
28 checked_impl!(CheckedAdd, checked_add, u128);
29 
30 checked_impl!(CheckedAdd, checked_add, i8);
31 checked_impl!(CheckedAdd, checked_add, i16);
32 checked_impl!(CheckedAdd, checked_add, i32);
33 checked_impl!(CheckedAdd, checked_add, i64);
34 checked_impl!(CheckedAdd, checked_add, isize);
35 #[cfg(has_i128)]
36 checked_impl!(CheckedAdd, checked_add, i128);
37 
38 /// Performs subtraction that returns `None` instead of wrapping around on underflow.
39 pub trait CheckedSub: Sized + Sub<Self, Output = Self> {
40     /// Subtracts two numbers, checking for underflow. If underflow happens,
41     /// `None` is returned.
checked_sub(&self, v: &Self) -> Option<Self>42     fn checked_sub(&self, v: &Self) -> Option<Self>;
43 }
44 
45 checked_impl!(CheckedSub, checked_sub, u8);
46 checked_impl!(CheckedSub, checked_sub, u16);
47 checked_impl!(CheckedSub, checked_sub, u32);
48 checked_impl!(CheckedSub, checked_sub, u64);
49 checked_impl!(CheckedSub, checked_sub, usize);
50 #[cfg(has_i128)]
51 checked_impl!(CheckedSub, checked_sub, u128);
52 
53 checked_impl!(CheckedSub, checked_sub, i8);
54 checked_impl!(CheckedSub, checked_sub, i16);
55 checked_impl!(CheckedSub, checked_sub, i32);
56 checked_impl!(CheckedSub, checked_sub, i64);
57 checked_impl!(CheckedSub, checked_sub, isize);
58 #[cfg(has_i128)]
59 checked_impl!(CheckedSub, checked_sub, i128);
60 
61 /// Performs multiplication that returns `None` instead of wrapping around on underflow or
62 /// overflow.
63 pub 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.
checked_mul(&self, v: &Self) -> Option<Self>66     fn checked_mul(&self, v: &Self) -> Option<Self>;
67 }
68 
69 checked_impl!(CheckedMul, checked_mul, u8);
70 checked_impl!(CheckedMul, checked_mul, u16);
71 checked_impl!(CheckedMul, checked_mul, u32);
72 checked_impl!(CheckedMul, checked_mul, u64);
73 checked_impl!(CheckedMul, checked_mul, usize);
74 #[cfg(has_i128)]
75 checked_impl!(CheckedMul, checked_mul, u128);
76 
77 checked_impl!(CheckedMul, checked_mul, i8);
78 checked_impl!(CheckedMul, checked_mul, i16);
79 checked_impl!(CheckedMul, checked_mul, i32);
80 checked_impl!(CheckedMul, checked_mul, i64);
81 checked_impl!(CheckedMul, checked_mul, isize);
82 #[cfg(has_i128)]
83 checked_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.
87 pub 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.
checked_div(&self, v: &Self) -> Option<Self>90     fn checked_div(&self, v: &Self) -> Option<Self>;
91 }
92 
93 checked_impl!(CheckedDiv, checked_div, u8);
94 checked_impl!(CheckedDiv, checked_div, u16);
95 checked_impl!(CheckedDiv, checked_div, u32);
96 checked_impl!(CheckedDiv, checked_div, u64);
97 checked_impl!(CheckedDiv, checked_div, usize);
98 #[cfg(has_i128)]
99 checked_impl!(CheckedDiv, checked_div, u128);
100 
101 checked_impl!(CheckedDiv, checked_div, i8);
102 checked_impl!(CheckedDiv, checked_div, i16);
103 checked_impl!(CheckedDiv, checked_div, i32);
104 checked_impl!(CheckedDiv, checked_div, i64);
105 checked_impl!(CheckedDiv, checked_div, isize);
106 #[cfg(has_i128)]
107 checked_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.
111 pub 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     /// ```
checked_rem(&self, v: &Self) -> Option<Self>131     fn checked_rem(&self, v: &Self) -> Option<Self>;
132 }
133 
134 checked_impl!(CheckedRem, checked_rem, u8);
135 checked_impl!(CheckedRem, checked_rem, u16);
136 checked_impl!(CheckedRem, checked_rem, u32);
137 checked_impl!(CheckedRem, checked_rem, u64);
138 checked_impl!(CheckedRem, checked_rem, usize);
139 #[cfg(has_i128)]
140 checked_impl!(CheckedRem, checked_rem, u128);
141 
142 checked_impl!(CheckedRem, checked_rem, i8);
143 checked_impl!(CheckedRem, checked_rem, i16);
144 checked_impl!(CheckedRem, checked_rem, i32);
145 checked_impl!(CheckedRem, checked_rem, i64);
146 checked_impl!(CheckedRem, checked_rem, isize);
147 #[cfg(has_i128)]
148 checked_impl!(CheckedRem, checked_rem, i128);
149 
150 macro_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.
162 pub 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     /// ```
checked_neg(&self) -> Option<Self>179     fn checked_neg(&self) -> Option<Self>;
180 }
181 
182 checked_impl_unary!(CheckedNeg, checked_neg, u8);
183 checked_impl_unary!(CheckedNeg, checked_neg, u16);
184 checked_impl_unary!(CheckedNeg, checked_neg, u32);
185 checked_impl_unary!(CheckedNeg, checked_neg, u64);
186 checked_impl_unary!(CheckedNeg, checked_neg, usize);
187 #[cfg(has_i128)]
188 checked_impl_unary!(CheckedNeg, checked_neg, u128);
189 
190 checked_impl_unary!(CheckedNeg, checked_neg, i8);
191 checked_impl_unary!(CheckedNeg, checked_neg, i16);
192 checked_impl_unary!(CheckedNeg, checked_neg, i32);
193 checked_impl_unary!(CheckedNeg, checked_neg, i64);
194 checked_impl_unary!(CheckedNeg, checked_neg, isize);
195 #[cfg(has_i128)]
196 checked_impl_unary!(CheckedNeg, checked_neg, i128);
197 
198 /// Performs a left shift that returns `None` on shifts larger than
199 /// the type width.
200 pub 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     /// ```
checked_shl(&self, rhs: u32) -> Option<Self>214     fn checked_shl(&self, rhs: u32) -> Option<Self>;
215 }
216 
217 macro_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 
228 checked_shift_impl!(CheckedShl, checked_shl, u8);
229 checked_shift_impl!(CheckedShl, checked_shl, u16);
230 checked_shift_impl!(CheckedShl, checked_shl, u32);
231 checked_shift_impl!(CheckedShl, checked_shl, u64);
232 checked_shift_impl!(CheckedShl, checked_shl, usize);
233 #[cfg(has_i128)]
234 checked_shift_impl!(CheckedShl, checked_shl, u128);
235 
236 checked_shift_impl!(CheckedShl, checked_shl, i8);
237 checked_shift_impl!(CheckedShl, checked_shl, i16);
238 checked_shift_impl!(CheckedShl, checked_shl, i32);
239 checked_shift_impl!(CheckedShl, checked_shl, i64);
240 checked_shift_impl!(CheckedShl, checked_shl, isize);
241 #[cfg(has_i128)]
242 checked_shift_impl!(CheckedShl, checked_shl, i128);
243 
244 /// Performs a right shift that returns `None` on shifts larger than
245 /// the type width.
246 pub 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     /// ```
checked_shr(&self, rhs: u32) -> Option<Self>260     fn checked_shr(&self, rhs: u32) -> Option<Self>;
261 }
262 
263 checked_shift_impl!(CheckedShr, checked_shr, u8);
264 checked_shift_impl!(CheckedShr, checked_shr, u16);
265 checked_shift_impl!(CheckedShr, checked_shr, u32);
266 checked_shift_impl!(CheckedShr, checked_shr, u64);
267 checked_shift_impl!(CheckedShr, checked_shr, usize);
268 #[cfg(has_i128)]
269 checked_shift_impl!(CheckedShr, checked_shr, u128);
270 
271 checked_shift_impl!(CheckedShr, checked_shr, i8);
272 checked_shift_impl!(CheckedShr, checked_shr, i16);
273 checked_shift_impl!(CheckedShr, checked_shr, i32);
274 checked_shift_impl!(CheckedShr, checked_shr, i64);
275 checked_shift_impl!(CheckedShr, checked_shr, isize);
276 #[cfg(has_i128)]
277 checked_shift_impl!(CheckedShr, checked_shr, i128);
278