checked.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. use core::ops::{Add, Sub, Mul, Div, Rem, Shl, Shr};
  2. /// Performs addition that returns `None` instead of wrapping around on
  3. /// overflow.
  4. pub trait CheckedAdd: Sized + Add<Self, Output=Self> {
  5. /// Adds two numbers, checking for overflow. If overflow happens, `None` is
  6. /// returned.
  7. fn checked_add(&self, v: &Self) -> Option<Self>;
  8. }
  9. macro_rules! checked_impl {
  10. ($trait_name:ident, $method:ident, $t:ty) => {
  11. impl $trait_name for $t {
  12. #[inline]
  13. fn $method(&self, v: &$t) -> Option<$t> {
  14. <$t>::$method(*self, *v)
  15. }
  16. }
  17. }
  18. }
  19. checked_impl!(CheckedAdd, checked_add, u8);
  20. checked_impl!(CheckedAdd, checked_add, u16);
  21. checked_impl!(CheckedAdd, checked_add, u32);
  22. checked_impl!(CheckedAdd, checked_add, u64);
  23. checked_impl!(CheckedAdd, checked_add, usize);
  24. #[cfg(feature = "i128")]
  25. checked_impl!(CheckedAdd, checked_add, u128);
  26. checked_impl!(CheckedAdd, checked_add, i8);
  27. checked_impl!(CheckedAdd, checked_add, i16);
  28. checked_impl!(CheckedAdd, checked_add, i32);
  29. checked_impl!(CheckedAdd, checked_add, i64);
  30. checked_impl!(CheckedAdd, checked_add, isize);
  31. #[cfg(feature = "i128")]
  32. checked_impl!(CheckedAdd, checked_add, i128);
  33. /// Performs subtraction that returns `None` instead of wrapping around on underflow.
  34. pub trait CheckedSub: Sized + Sub<Self, Output=Self> {
  35. /// Subtracts two numbers, checking for underflow. If underflow happens,
  36. /// `None` is returned.
  37. fn checked_sub(&self, v: &Self) -> Option<Self>;
  38. }
  39. checked_impl!(CheckedSub, checked_sub, u8);
  40. checked_impl!(CheckedSub, checked_sub, u16);
  41. checked_impl!(CheckedSub, checked_sub, u32);
  42. checked_impl!(CheckedSub, checked_sub, u64);
  43. checked_impl!(CheckedSub, checked_sub, usize);
  44. #[cfg(feature = "i128")]
  45. checked_impl!(CheckedSub, checked_sub, u128);
  46. checked_impl!(CheckedSub, checked_sub, i8);
  47. checked_impl!(CheckedSub, checked_sub, i16);
  48. checked_impl!(CheckedSub, checked_sub, i32);
  49. checked_impl!(CheckedSub, checked_sub, i64);
  50. checked_impl!(CheckedSub, checked_sub, isize);
  51. #[cfg(feature = "i128")]
  52. checked_impl!(CheckedSub, checked_sub, i128);
  53. /// Performs multiplication that returns `None` instead of wrapping around on underflow or
  54. /// overflow.
  55. pub trait CheckedMul: Sized + Mul<Self, Output=Self> {
  56. /// Multiplies two numbers, checking for underflow or overflow. If underflow
  57. /// or overflow happens, `None` is returned.
  58. fn checked_mul(&self, v: &Self) -> Option<Self>;
  59. }
  60. checked_impl!(CheckedMul, checked_mul, u8);
  61. checked_impl!(CheckedMul, checked_mul, u16);
  62. checked_impl!(CheckedMul, checked_mul, u32);
  63. checked_impl!(CheckedMul, checked_mul, u64);
  64. checked_impl!(CheckedMul, checked_mul, usize);
  65. #[cfg(feature = "i128")]
  66. checked_impl!(CheckedMul, checked_mul, u128);
  67. checked_impl!(CheckedMul, checked_mul, i8);
  68. checked_impl!(CheckedMul, checked_mul, i16);
  69. checked_impl!(CheckedMul, checked_mul, i32);
  70. checked_impl!(CheckedMul, checked_mul, i64);
  71. checked_impl!(CheckedMul, checked_mul, isize);
  72. #[cfg(feature = "i128")]
  73. checked_impl!(CheckedMul, checked_mul, i128);
  74. /// Performs division that returns `None` instead of panicking on division by zero and instead of
  75. /// wrapping around on underflow and overflow.
  76. pub trait CheckedDiv: Sized + Div<Self, Output=Self> {
  77. /// Divides two numbers, checking for underflow, overflow and division by
  78. /// zero. If any of that happens, `None` is returned.
  79. fn checked_div(&self, v: &Self) -> Option<Self>;
  80. }
  81. checked_impl!(CheckedDiv, checked_div, u8);
  82. checked_impl!(CheckedDiv, checked_div, u16);
  83. checked_impl!(CheckedDiv, checked_div, u32);
  84. checked_impl!(CheckedDiv, checked_div, u64);
  85. checked_impl!(CheckedDiv, checked_div, usize);
  86. #[cfg(feature = "i128")]
  87. checked_impl!(CheckedDiv, checked_div, u128);
  88. checked_impl!(CheckedDiv, checked_div, i8);
  89. checked_impl!(CheckedDiv, checked_div, i16);
  90. checked_impl!(CheckedDiv, checked_div, i32);
  91. checked_impl!(CheckedDiv, checked_div, i64);
  92. checked_impl!(CheckedDiv, checked_div, isize);
  93. #[cfg(feature = "i128")]
  94. checked_impl!(CheckedDiv, checked_div, i128);
  95. /// Performs an integral remainder that returns `None` instead of panicking on division by zero and
  96. /// instead of wrapping around on underflow and overflow.
  97. pub trait CheckedRem: Sized + Rem<Self, Output = Self> {
  98. /// Finds the remainder of dividing two numbers, checking for underflow, overflow and division
  99. /// by zero. If any of that happens, `None` is returned.
  100. ///
  101. /// # Examples
  102. ///
  103. /// ```
  104. /// use num_traits::CheckedRem;
  105. /// use std::i32::MIN;
  106. ///
  107. /// assert_eq!(CheckedRem::checked_rem(&10, &7), Some(3));
  108. /// assert_eq!(CheckedRem::checked_rem(&10, &-7), Some(3));
  109. /// assert_eq!(CheckedRem::checked_rem(&-10, &7), Some(-3));
  110. /// assert_eq!(CheckedRem::checked_rem(&-10, &-7), Some(-3));
  111. ///
  112. /// assert_eq!(CheckedRem::checked_rem(&10, &0), None);
  113. ///
  114. /// assert_eq!(CheckedRem::checked_rem(&MIN, &1), Some(0));
  115. /// assert_eq!(CheckedRem::checked_rem(&MIN, &-1), None);
  116. /// ```
  117. fn checked_rem(&self, v: &Self) -> Option<Self>;
  118. }
  119. checked_impl!(CheckedRem, checked_rem, u8);
  120. checked_impl!(CheckedRem, checked_rem, u16);
  121. checked_impl!(CheckedRem, checked_rem, u32);
  122. checked_impl!(CheckedRem, checked_rem, u64);
  123. checked_impl!(CheckedRem, checked_rem, usize);
  124. #[cfg(feature = "i128")]
  125. checked_impl!(CheckedRem, checked_rem, u128);
  126. checked_impl!(CheckedRem, checked_rem, i8);
  127. checked_impl!(CheckedRem, checked_rem, i16);
  128. checked_impl!(CheckedRem, checked_rem, i32);
  129. checked_impl!(CheckedRem, checked_rem, i64);
  130. checked_impl!(CheckedRem, checked_rem, isize);
  131. #[cfg(feature = "i128")]
  132. checked_impl!(CheckedRem, checked_rem, i128);
  133. macro_rules! checked_impl_unary {
  134. ($trait_name:ident, $method:ident, $t:ty) => {
  135. impl $trait_name for $t {
  136. #[inline]
  137. fn $method(&self) -> Option<$t> {
  138. <$t>::$method(*self)
  139. }
  140. }
  141. }
  142. }
  143. /// Performs negation that returns `None` if the result can't be represented.
  144. pub trait CheckedNeg: Sized {
  145. /// Negates a number, returning `None` for results that can't be represented, like signed `MIN`
  146. /// values that can't be positive, or non-zero unsigned values that can't be negative.
  147. ///
  148. /// # Examples
  149. ///
  150. /// ```
  151. /// use num_traits::CheckedNeg;
  152. /// use std::i32::MIN;
  153. ///
  154. /// assert_eq!(CheckedNeg::checked_neg(&1_i32), Some(-1));
  155. /// assert_eq!(CheckedNeg::checked_neg(&-1_i32), Some(1));
  156. /// assert_eq!(CheckedNeg::checked_neg(&MIN), None);
  157. ///
  158. /// assert_eq!(CheckedNeg::checked_neg(&0_u32), Some(0));
  159. /// assert_eq!(CheckedNeg::checked_neg(&1_u32), None);
  160. /// ```
  161. fn checked_neg(&self) -> Option<Self>;
  162. }
  163. checked_impl_unary!(CheckedNeg, checked_neg, u8);
  164. checked_impl_unary!(CheckedNeg, checked_neg, u16);
  165. checked_impl_unary!(CheckedNeg, checked_neg, u32);
  166. checked_impl_unary!(CheckedNeg, checked_neg, u64);
  167. checked_impl_unary!(CheckedNeg, checked_neg, usize);
  168. #[cfg(feature = "i128")]
  169. checked_impl_unary!(CheckedNeg, checked_neg, u128);
  170. checked_impl_unary!(CheckedNeg, checked_neg, i8);
  171. checked_impl_unary!(CheckedNeg, checked_neg, i16);
  172. checked_impl_unary!(CheckedNeg, checked_neg, i32);
  173. checked_impl_unary!(CheckedNeg, checked_neg, i64);
  174. checked_impl_unary!(CheckedNeg, checked_neg, isize);
  175. #[cfg(feature = "i128")]
  176. checked_impl_unary!(CheckedNeg, checked_neg, i128);
  177. /// Performs a left shift that returns `None` on overflow.
  178. pub trait CheckedShl: Sized + Shl<u32, Output=Self> {
  179. /// Shifts a number to the left, checking for overflow. If overflow happens,
  180. /// `None` is returned.
  181. ///
  182. /// ```
  183. /// use num_traits::CheckedShl;
  184. ///
  185. /// let x: u16 = 0x0001;
  186. ///
  187. /// assert_eq!(CheckedShl::checked_shl(&x, 0), Some(0x0001));
  188. /// assert_eq!(CheckedShl::checked_shl(&x, 1), Some(0x0002));
  189. /// assert_eq!(CheckedShl::checked_shl(&x, 15), Some(0x8000));
  190. /// assert_eq!(CheckedShl::checked_shl(&x, 16), None);
  191. /// ```
  192. fn checked_shl(&self, rhs: u32) -> Option<Self>;
  193. }
  194. macro_rules! checked_shift_impl {
  195. ($trait_name:ident, $method:ident, $t:ty) => {
  196. impl $trait_name for $t {
  197. #[inline]
  198. fn $method(&self, rhs: u32) -> Option<$t> {
  199. <$t>::$method(*self, rhs)
  200. }
  201. }
  202. }
  203. }
  204. checked_shift_impl!(CheckedShl, checked_shl, u8);
  205. checked_shift_impl!(CheckedShl, checked_shl, u16);
  206. checked_shift_impl!(CheckedShl, checked_shl, u32);
  207. checked_shift_impl!(CheckedShl, checked_shl, u64);
  208. checked_shift_impl!(CheckedShl, checked_shl, usize);
  209. #[cfg(feature = "i128")]
  210. checked_shift_impl!(CheckedShl, checked_shl, u128);
  211. checked_shift_impl!(CheckedShl, checked_shl, i8);
  212. checked_shift_impl!(CheckedShl, checked_shl, i16);
  213. checked_shift_impl!(CheckedShl, checked_shl, i32);
  214. checked_shift_impl!(CheckedShl, checked_shl, i64);
  215. checked_shift_impl!(CheckedShl, checked_shl, isize);
  216. #[cfg(feature = "i128")]
  217. checked_shift_impl!(CheckedShl, checked_shl, i128);
  218. /// Performs a right shift that returns `None` on overflow.
  219. pub trait CheckedShr: Sized + Shr<u32, Output=Self> {
  220. /// Shifts a number to the left, checking for overflow. If overflow happens,
  221. /// `None` is returned.
  222. ///
  223. /// ```
  224. /// use num_traits::CheckedShr;
  225. ///
  226. /// let x: u16 = 0x8000;
  227. ///
  228. /// assert_eq!(CheckedShr::checked_shr(&x, 0), Some(0x8000));
  229. /// assert_eq!(CheckedShr::checked_shr(&x, 1), Some(0x4000));
  230. /// assert_eq!(CheckedShr::checked_shr(&x, 15), Some(0x0001));
  231. /// assert_eq!(CheckedShr::checked_shr(&x, 16), None);
  232. /// ```
  233. fn checked_shr(&self, rhs: u32) -> Option<Self>;
  234. }
  235. checked_shift_impl!(CheckedShr, checked_shr, u8);
  236. checked_shift_impl!(CheckedShr, checked_shr, u16);
  237. checked_shift_impl!(CheckedShr, checked_shr, u32);
  238. checked_shift_impl!(CheckedShr, checked_shr, u64);
  239. checked_shift_impl!(CheckedShr, checked_shr, usize);
  240. #[cfg(feature = "i128")]
  241. checked_shift_impl!(CheckedShr, checked_shr, u128);
  242. checked_shift_impl!(CheckedShr, checked_shr, i8);
  243. checked_shift_impl!(CheckedShr, checked_shr, i16);
  244. checked_shift_impl!(CheckedShr, checked_shr, i32);
  245. checked_shift_impl!(CheckedShr, checked_shr, i64);
  246. checked_shift_impl!(CheckedShr, checked_shr, isize);
  247. #[cfg(feature = "i128")]
  248. checked_shift_impl!(CheckedShr, checked_shr, i128);