| 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 | |