checked.rs 8.9 KB

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