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. |
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. |
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. |
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. |
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 | /// ``` |
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 | /// ``` |
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 | /// ``` |
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 | /// ``` |
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 | |