identities.rs 4.0 KB

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