identities.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. use std::ops::{Add, Mul};
  2. use std::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. // FIXME (#5527): This should be an associated constant
  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. // FIXME (#5527): This should be an associated constant
  72. fn one() -> Self;
  73. }
  74. macro_rules! one_impl {
  75. ($t:ty, $v:expr) => {
  76. impl One for $t {
  77. #[inline]
  78. fn one() -> $t { $v }
  79. }
  80. }
  81. }
  82. one_impl!(usize, 1usize);
  83. one_impl!(u8, 1u8);
  84. one_impl!(u16, 1u16);
  85. one_impl!(u32, 1u32);
  86. one_impl!(u64, 1u64);
  87. one_impl!(isize, 1isize);
  88. one_impl!(i8, 1i8);
  89. one_impl!(i16, 1i16);
  90. one_impl!(i32, 1i32);
  91. one_impl!(i64, 1i64);
  92. one_impl!(f32, 1.0f32);
  93. one_impl!(f64, 1.0f64);
  94. impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
  95. fn one() -> Self {
  96. Wrapping(T::one())
  97. }
  98. }
  99. // Some helper functions provided for backwards compatibility.
  100. /// Returns the additive identity, `0`.
  101. #[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
  102. /// Returns the multiplicative identity, `1`.
  103. #[inline(always)] pub fn one<T: One>() -> T { One::one() }
  104. #[test]
  105. fn wrapping_identities() {
  106. macro_rules! test_wrapping_identities {
  107. ($($t:ty)+) => {
  108. $(
  109. assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0);
  110. assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0);
  111. assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero());
  112. assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero());
  113. )+
  114. };
  115. }
  116. test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
  117. }
  118. #[test]
  119. fn wrapping_is_zero() {
  120. fn require_zero<T: Zero>(_: &T) {}
  121. require_zero(&Wrapping(42));
  122. }
  123. #[test]
  124. fn wrapping_is_one() {
  125. fn require_one<T: One>(_: &T) {}
  126. require_one(&Wrapping(42));
  127. }