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