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

2 | use core::ops::Neg; |

3 | |

4 | use crate::float::FloatCore; |

5 | use crate::Num; |

6 | |

7 | /// Useful functions for signed numbers (i.e. numbers that can be negative). |

8 | pub trait Signed: Sized + Num + Neg<Output = Self> { |

9 | /// Computes the absolute value. |

10 | /// |

11 | /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`. |

12 | /// |

13 | /// For signed integers, `::MIN` will be returned if the number is `::MIN`. |

14 | fn abs(&self) -> Self; |

15 | |

16 | /// The positive difference of two numbers. |

17 | /// |

18 | /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference |

19 | /// between `self` and `other` is returned. |

20 | fn abs_sub(&self, other: &Self) -> Self; |

21 | |

22 | /// Returns the sign of the number. |

23 | /// |

24 | /// For `f32` and `f64`: |

25 | /// |

26 | /// * `1.0` if the number is positive, `+0.0` or `INFINITY` |

27 | /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` |

28 | /// * `NaN` if the number is `NaN` |

29 | /// |

30 | /// For signed integers: |

31 | /// |

32 | /// * `0` if the number is zero |

33 | /// * `1` if the number is positive |

34 | /// * `-1` if the number is negative |

35 | fn signum(&self) -> Self; |

36 | |

37 | /// Returns true if the number is positive and false if the number is zero or negative. |

38 | fn is_positive(&self) -> bool; |

39 | |

40 | /// Returns true if the number is negative and false if the number is zero or positive. |

41 | fn is_negative(&self) -> bool; |

42 | } |

43 | |

44 | macro_rules! signed_impl { |

45 | ($($t:ty)*) => ($( |

46 | impl Signed for $t { |

47 | #[inline] |

48 | fn abs(&self) -> $t { |

49 | if self.is_negative() { -*self } else { *self } |

50 | } |

51 | |

52 | #[inline] |

53 | fn abs_sub(&self, other: &$t) -> $t { |

54 | if *self <= *other { 0 } else { *self - *other } |

55 | } |

56 | |

57 | #[inline] |

58 | fn signum(&self) -> $t { |

59 | match *self { |

60 | n if n > 0 => 1, |

61 | 0 => 0, |

62 | _ => -1, |

63 | } |

64 | } |

65 | |

66 | #[inline] |

67 | fn is_positive(&self) -> bool { *self > 0 } |

68 | |

69 | #[inline] |

70 | fn is_negative(&self) -> bool { *self < 0 } |

71 | } |

72 | )*) |

73 | } |

74 | |

75 | signed_impl!(isize i8 i16 i32 i64 i128); |

76 | |

77 | impl<T: Signed> Signed for Wrapping<T> |

78 | where |

79 | Wrapping<T>: Num + Neg<Output = Wrapping<T>>, |

80 | { |

81 | #[inline] |

82 | fn abs(&self) -> Self { |

83 | Wrapping(self.0.abs()) |

84 | } |

85 | |

86 | #[inline] |

87 | fn abs_sub(&self, other: &Self) -> Self { |

88 | Wrapping(self.0.abs_sub(&other.0)) |

89 | } |

90 | |

91 | #[inline] |

92 | fn signum(&self) -> Self { |

93 | Wrapping(self.0.signum()) |

94 | } |

95 | |

96 | #[inline] |

97 | fn is_positive(&self) -> bool { |

98 | self.0.is_positive() |

99 | } |

100 | |

101 | #[inline] |

102 | fn is_negative(&self) -> bool { |

103 | self.0.is_negative() |

104 | } |

105 | } |

106 | |

107 | macro_rules! signed_float_impl { |

108 | ($t:ty) => { |

109 | impl Signed for $t { |

110 | /// Computes the absolute value. Returns `NAN` if the number is `NAN`. |

111 | #[inline] |

112 | fn abs(&self) -> $t { |

113 | FloatCore::abs(*self) |

114 | } |

115 | |

116 | /// The positive difference of two numbers. Returns `0.0` if the number is |

117 | /// less than or equal to `other`, otherwise the difference between`self` |

118 | /// and `other` is returned. |

119 | #[inline] |

120 | fn abs_sub(&self, other: &$t) -> $t { |

121 | if *self <= *other { |

122 | 0. |

123 | } else { |

124 | *self - *other |

125 | } |

126 | } |

127 | |

128 | /// # Returns |

129 | /// |

130 | /// - `1.0` if the number is positive, `+0.0` or `INFINITY` |

131 | /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` |

132 | /// - `NAN` if the number is NaN |

133 | #[inline] |

134 | fn signum(&self) -> $t { |

135 | FloatCore::signum(*self) |

136 | } |

137 | |

138 | /// Returns `true` if the number is positive, including `+0.0` and `INFINITY` |

139 | #[inline] |

140 | fn is_positive(&self) -> bool { |

141 | FloatCore::is_sign_positive(*self) |

142 | } |

143 | |

144 | /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY` |

145 | #[inline] |

146 | fn is_negative(&self) -> bool { |

147 | FloatCore::is_sign_negative(*self) |

148 | } |

149 | } |

150 | }; |

151 | } |

152 | |

153 | signed_float_impl!(f32); |

154 | signed_float_impl!(f64); |

155 | |

156 | /// Computes the absolute value. |

157 | /// |

158 | /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN` |

159 | /// |

160 | /// For signed integers, `::MIN` will be returned if the number is `::MIN`. |

161 | #[inline(always)] |

162 | pub fn abs<T: Signed>(value: T) -> T { |

163 | value.abs() |

164 | } |

165 | |

166 | /// The positive difference of two numbers. |

167 | /// |

168 | /// Returns zero if `x` is less than or equal to `y`, otherwise the difference |

169 | /// between `x` and `y` is returned. |

170 | #[inline(always)] |

171 | pub fn abs_sub<T: Signed>(x: T, y: T) -> T { |

172 | x.abs_sub(&y) |

173 | } |

174 | |

175 | /// Returns the sign of the number. |

176 | /// |

177 | /// For `f32` and `f64`: |

178 | /// |

179 | /// * `1.0` if the number is positive, `+0.0` or `INFINITY` |

180 | /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` |

181 | /// * `NaN` if the number is `NaN` |

182 | /// |

183 | /// For signed integers: |

184 | /// |

185 | /// * `0` if the number is zero |

186 | /// * `1` if the number is positive |

187 | /// * `-1` if the number is negative |

188 | #[inline(always)] |

189 | pub fn signum<T: Signed>(value: T) -> T { |

190 | value.signum() |

191 | } |

192 | |

193 | /// A trait for values which cannot be negative |

194 | pub trait Unsigned: Num {} |

195 | |

196 | macro_rules! empty_trait_impl { |

197 | ($name:ident for $($t:ty)*) => ($( |

198 | impl $name for $t {} |

199 | )*) |

200 | } |

201 | |

202 | empty_trait_impl!(Unsigned for usize u8 u16 u32 u64 u128); |

203 | |

204 | impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {} |

205 | |

206 | #[test] |

207 | fn unsigned_wrapping_is_unsigned() { |

208 | fn require_unsigned<T: Unsigned>(_: &T) {} |

209 | require_unsigned(&Wrapping(42_u32)); |

210 | } |

211 | |

212 | #[test] |

213 | fn signed_wrapping_is_signed() { |

214 | fn require_signed<T: Signed>(_: &T) {} |

215 | require_signed(&Wrapping(-42)); |

216 | } |

217 |