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