1 | use core::num::Wrapping; |
---|---|

2 | use core::ops::{Add, Mul}; |

3 | |

4 | /// Defines an additive identity element for `Self`. |

5 | /// |

6 | /// # Laws |

7 | /// |

8 | /// ```text |

9 | /// a + 0 = a ∀ a ∈ Self |

10 | /// 0 + a = a ∀ a ∈ Self |

11 | /// ``` |

12 | pub trait Zero: Sized + Add<Self, Output = Self> { |

13 | /// Returns the additive identity element of `Self`, `0`. |

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 | |

22 | /// Sets `self` to the additive identity element of `Self`, `0`. |

23 | fn set_zero(&mut self) { |

24 | *self = Zero::zero(); |

25 | } |

26 | |

27 | /// Returns `true` if `self` is equal to the additive identity. |

28 | fn is_zero(&self) -> bool; |

29 | } |

30 | |

31 | macro_rules! zero_impl { |

32 | ($t:ty, $v:expr) => { |

33 | impl Zero for $t { |

34 | #[inline] |

35 | fn zero() -> $t { |

36 | $v |

37 | } |

38 | #[inline] |

39 | fn is_zero(&self) -> bool { |

40 | *self == $v |

41 | } |

42 | } |

43 | }; |

44 | } |

45 | |

46 | zero_impl!(usize, 0); |

47 | zero_impl!(u8, 0); |

48 | zero_impl!(u16, 0); |

49 | zero_impl!(u32, 0); |

50 | zero_impl!(u64, 0); |

51 | zero_impl!(u128, 0); |

52 | |

53 | zero_impl!(isize, 0); |

54 | zero_impl!(i8, 0); |

55 | zero_impl!(i16, 0); |

56 | zero_impl!(i32, 0); |

57 | zero_impl!(i64, 0); |

58 | zero_impl!(i128, 0); |

59 | |

60 | zero_impl!(f32, 0.0); |

61 | zero_impl!(f64, 0.0); |

62 | |

63 | impl<T: Zero> Zero for Wrapping<T> |

64 | where |

65 | Wrapping<T>: Add<Output = Wrapping<T>>, |

66 | { |

67 | fn is_zero(&self) -> bool { |

68 | self.0.is_zero() |

69 | } |

70 | |

71 | fn set_zero(&mut self) { |

72 | self.0.set_zero(); |

73 | } |

74 | |

75 | fn zero() -> Self { |

76 | Wrapping(T::zero()) |

77 | } |

78 | } |

79 | |

80 | /// Defines a multiplicative identity element for `Self`. |

81 | /// |

82 | /// # Laws |

83 | /// |

84 | /// ```text |

85 | /// a * 1 = a ∀ a ∈ Self |

86 | /// 1 * a = a ∀ a ∈ Self |

87 | /// ``` |

88 | pub trait One: Sized + Mul<Self, Output = Self> { |

89 | /// Returns the multiplicative identity element of `Self`, `1`. |

90 | /// |

91 | /// # Purity |

92 | /// |

93 | /// This function should return the same result at all times regardless of |

94 | /// external mutable state, for example values stored in TLS or in |

95 | /// `static mut`s. |

96 | // This cannot be an associated constant, because of bignums. |

97 | fn one() -> Self; |

98 | |

99 | /// Sets `self` to the multiplicative identity element of `Self`, `1`. |

100 | fn set_one(&mut self) { |

101 | *self = One::one(); |

102 | } |

103 | |

104 | /// Returns `true` if `self` is equal to the multiplicative identity. |

105 | /// |

106 | /// For performance reasons, it's best to implement this manually. |

107 | /// After a semver bump, this method will be required, and the |

108 | /// `where Self: PartialEq` bound will be removed. |

109 | #[inline] |

110 | fn is_one(&self) -> bool |

111 | where |

112 | Self: PartialEq, |

113 | { |

114 | *self == Self::one() |

115 | } |

116 | } |

117 | |

118 | macro_rules! one_impl { |

119 | ($t:ty, $v:expr) => { |

120 | impl One for $t { |

121 | #[inline] |

122 | fn one() -> $t { |

123 | $v |

124 | } |

125 | #[inline] |

126 | fn is_one(&self) -> bool { |

127 | *self == $v |

128 | } |

129 | } |

130 | }; |

131 | } |

132 | |

133 | one_impl!(usize, 1); |

134 | one_impl!(u8, 1); |

135 | one_impl!(u16, 1); |

136 | one_impl!(u32, 1); |

137 | one_impl!(u64, 1); |

138 | one_impl!(u128, 1); |

139 | |

140 | one_impl!(isize, 1); |

141 | one_impl!(i8, 1); |

142 | one_impl!(i16, 1); |

143 | one_impl!(i32, 1); |

144 | one_impl!(i64, 1); |

145 | one_impl!(i128, 1); |

146 | |

147 | one_impl!(f32, 1.0); |

148 | one_impl!(f64, 1.0); |

149 | |

150 | impl<T: One> One for Wrapping<T> |

151 | where |

152 | Wrapping<T>: Mul<Output = Wrapping<T>>, |

153 | { |

154 | fn set_one(&mut self) { |

155 | self.0.set_one(); |

156 | } |

157 | |

158 | fn one() -> Self { |

159 | Wrapping(T::one()) |

160 | } |

161 | } |

162 | |

163 | // Some helper functions provided for backwards compatibility. |

164 | |

165 | /// Returns the additive identity, `0`. |

166 | #[inline(always)] |

167 | pub fn zero<T: Zero>() -> T { |

168 | Zero::zero() |

169 | } |

170 | |

171 | /// Returns the multiplicative identity, `1`. |

172 | #[inline(always)] |

173 | pub fn one<T: One>() -> T { |

174 | One::one() |

175 | } |

176 | |

177 | #[test] |

178 | fn wrapping_identities() { |

179 | macro_rules! test_wrapping_identities { |

180 | ($($t:ty)+) => { |

181 | $( |

182 | assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0); |

183 | assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0); |

184 | assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero()); |

185 | assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero()); |

186 | )+ |

187 | }; |

188 | } |

189 | |

190 | test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); |

191 | } |

192 | |

193 | #[test] |

194 | fn wrapping_is_zero() { |

195 | fn require_zero<T: Zero>(_: &T) {} |

196 | require_zero(&Wrapping(42)); |

197 | } |

198 | #[test] |

199 | fn wrapping_is_one() { |

200 | fn require_one<T: One>(_: &T) {} |

201 | require_one(&Wrapping(42)); |

202 | } |

203 |