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