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