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