identities.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. use core::ops::{Add, Mul};
  2. use core::num::Wrapping;
  3. /// Defines an additive identity element for `Self`.
  4. pub trait Zero: Sized + Add<Self, Output = Self> {
  5. /// Returns the additive identity element of `Self`, `0`.
  6. ///
  7. /// # Laws
  8. ///
  9. /// ```{.text}
  10. /// a + 0 = a ∀ a ∈ Self
  11. /// 0 + a = a ∀ a ∈ Self
  12. /// ```
  13. ///
  14. /// # Purity
  15. ///
  16. /// This function should return the same result at all times regardless of
  17. /// external mutable state, for example values stored in TLS or in
  18. /// `static mut`s.
  19. // This cannot be an associated constant, because of bignums.
  20. fn zero() -> Self;
  21. /// Returns `true` if `self` is equal to the additive identity.
  22. #[inline]
  23. fn is_zero(&self) -> bool;
  24. }
  25. macro_rules! zero_impl {
  26. ($t:ty, $v:expr) => {
  27. impl Zero for $t {
  28. #[inline]
  29. fn zero() -> $t { $v }
  30. #[inline]
  31. fn is_zero(&self) -> bool { *self == $v }
  32. }
  33. }
  34. }
  35. zero_impl!(usize, 0);
  36. zero_impl!(u8, 0);
  37. zero_impl!(u16, 0);
  38. zero_impl!(u32, 0);
  39. zero_impl!(u64, 0);
  40. #[cfg(has_i128)]
  41. zero_impl!(u128, 0);
  42. zero_impl!(isize, 0);
  43. zero_impl!(i8, 0);
  44. zero_impl!(i16, 0);
  45. zero_impl!(i32, 0);
  46. zero_impl!(i64, 0);
  47. #[cfg(has_i128)]
  48. zero_impl!(i128, 0);
  49. zero_impl!(f32, 0.0);
  50. zero_impl!(f64, 0.0);
  51. impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output=Wrapping<T>> {
  52. fn is_zero(&self) -> bool {
  53. self.0.is_zero()
  54. }
  55. fn zero() -> Self {
  56. Wrapping(T::zero())
  57. }
  58. }
  59. /// Defines a multiplicative identity element for `Self`.
  60. pub trait One: Sized + Mul<Self, Output = Self> {
  61. /// Returns the multiplicative identity element of `Self`, `1`.
  62. ///
  63. /// # Laws
  64. ///
  65. /// ```{.text}
  66. /// a * 1 = a ∀ a ∈ Self
  67. /// 1 * a = a ∀ a ∈ Self
  68. /// ```
  69. ///
  70. /// # Purity
  71. ///
  72. /// This function should return the same result at all times regardless of
  73. /// external mutable state, for example values stored in TLS or in
  74. /// `static mut`s.
  75. // This cannot be an associated constant, because of bignums.
  76. fn one() -> Self;
  77. /// Returns `true` if `self` is equal to the multiplicative identity.
  78. ///
  79. /// For performance reasons, it's best to implement this manually.
  80. /// After a semver bump, this method will be required, and the
  81. /// `where Self: PartialEq` bound will be removed.
  82. #[inline]
  83. fn is_one(&self) -> bool where Self: PartialEq {
  84. *self == Self::one()
  85. }
  86. }
  87. macro_rules! one_impl {
  88. ($t:ty, $v:expr) => {
  89. impl One for $t {
  90. #[inline]
  91. fn one() -> $t { $v }
  92. }
  93. }
  94. }
  95. one_impl!(usize, 1);
  96. one_impl!(u8, 1);
  97. one_impl!(u16, 1);
  98. one_impl!(u32, 1);
  99. one_impl!(u64, 1);
  100. #[cfg(has_i128)]
  101. one_impl!(u128, 1);
  102. one_impl!(isize, 1);
  103. one_impl!(i8, 1);
  104. one_impl!(i16, 1);
  105. one_impl!(i32, 1);
  106. one_impl!(i64, 1);
  107. #[cfg(has_i128)]
  108. one_impl!(i128, 1);
  109. one_impl!(f32, 1.0);
  110. one_impl!(f64, 1.0);
  111. impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
  112. fn one() -> Self {
  113. Wrapping(T::one())
  114. }
  115. }
  116. // Some helper functions provided for backwards compatibility.
  117. /// Returns the additive identity, `0`.
  118. #[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
  119. /// Returns the multiplicative identity, `1`.
  120. #[inline(always)] pub fn one<T: One>() -> T { One::one() }
  121. #[test]
  122. fn wrapping_identities() {
  123. macro_rules! test_wrapping_identities {
  124. ($($t:ty)+) => {
  125. $(
  126. assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0);
  127. assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0);
  128. assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero());
  129. assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero());
  130. )+
  131. };
  132. }
  133. test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
  134. }
  135. #[test]
  136. fn wrapping_is_zero() {
  137. fn require_zero<T: Zero>(_: &T) {}
  138. require_zero(&Wrapping(42));
  139. }
  140. #[test]
  141. fn wrapping_is_one() {
  142. fn require_one<T: One>(_: &T) {}
  143. require_one(&Wrapping(42));
  144. }