1 use core::num::Wrapping;
2 use core::ops::Neg;
3 
4 use float::FloatCore;
5 use 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`.
abs(&self) -> Self14     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.
abs_sub(&self, other: &Self) -> Self20     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
signum(&self) -> Self35     fn signum(&self) -> Self;
36 
37     /// Returns true if the number is positive and false if the number is zero or negative.
is_positive(&self) -> bool38     fn is_positive(&self) -> bool;
39 
40     /// Returns true if the number is negative and false if the number is zero or positive.
is_negative(&self) -> bool41     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);
76 
77 #[cfg(has_i128)]
78 signed_impl!(i128);
79 
80 impl<T: Signed> Signed for Wrapping<T>
81 where
82     Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
83 {
84     #[inline]
abs(&self) -> Self85     fn abs(&self) -> Self {
86         Wrapping(self.0.abs())
87     }
88 
89     #[inline]
abs_sub(&self, other: &Self) -> Self90     fn abs_sub(&self, other: &Self) -> Self {
91         Wrapping(self.0.abs_sub(&other.0))
92     }
93 
94     #[inline]
signum(&self) -> Self95     fn signum(&self) -> Self {
96         Wrapping(self.0.signum())
97     }
98 
99     #[inline]
is_positive(&self) -> bool100     fn is_positive(&self) -> bool {
101         self.0.is_positive()
102     }
103 
104     #[inline]
is_negative(&self) -> bool105     fn is_negative(&self) -> bool {
106         self.0.is_negative()
107     }
108 }
109 
110 macro_rules! signed_float_impl {
111     ($t:ty) => {
112         impl Signed for $t {
113             /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
114             #[inline]
115             fn abs(&self) -> $t {
116                 FloatCore::abs(*self)
117             }
118 
119             /// The positive difference of two numbers. Returns `0.0` if the number is
120             /// less than or equal to `other`, otherwise the difference between`self`
121             /// and `other` is returned.
122             #[inline]
123             fn abs_sub(&self, other: &$t) -> $t {
124                 if *self <= *other {
125                     0.
126                 } else {
127                     *self - *other
128                 }
129             }
130 
131             /// # Returns
132             ///
133             /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
134             /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
135             /// - `NAN` if the number is NaN
136             #[inline]
137             fn signum(&self) -> $t {
138                 FloatCore::signum(*self)
139             }
140 
141             /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
142             #[inline]
143             fn is_positive(&self) -> bool {
144                 FloatCore::is_sign_positive(*self)
145             }
146 
147             /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
148             #[inline]
149             fn is_negative(&self) -> bool {
150                 FloatCore::is_sign_negative(*self)
151             }
152         }
153     };
154 }
155 
156 signed_float_impl!(f32);
157 signed_float_impl!(f64);
158 
159 /// Computes the absolute value.
160 ///
161 /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
162 ///
163 /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
164 #[inline(always)]
abs<T: Signed>(value: T) -> T165 pub fn abs<T: Signed>(value: T) -> T {
166     value.abs()
167 }
168 
169 /// The positive difference of two numbers.
170 ///
171 /// Returns zero if `x` is less than or equal to `y`, otherwise the difference
172 /// between `x` and `y` is returned.
173 #[inline(always)]
abs_sub<T: Signed>(x: T, y: T) -> T174 pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
175     x.abs_sub(&y)
176 }
177 
178 /// Returns the sign of the number.
179 ///
180 /// For `f32` and `f64`:
181 ///
182 /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
183 /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
184 /// * `NaN` if the number is `NaN`
185 ///
186 /// For signed integers:
187 ///
188 /// * `0` if the number is zero
189 /// * `1` if the number is positive
190 /// * `-1` if the number is negative
191 #[inline(always)]
signum<T: Signed>(value: T) -> T192 pub fn signum<T: Signed>(value: T) -> T {
193     value.signum()
194 }
195 
196 /// A trait for values which cannot be negative
197 pub trait Unsigned: Num {}
198 
199 macro_rules! empty_trait_impl {
200     ($name:ident for $($t:ty)*) => ($(
201         impl $name for $t {}
202     )*)
203 }
204 
205 empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
206 #[cfg(has_i128)]
207 empty_trait_impl!(Unsigned for u128);
208 
209 impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}
210 
211 #[test]
unsigned_wrapping_is_unsigned()212 fn unsigned_wrapping_is_unsigned() {
213     fn require_unsigned<T: Unsigned>(_: &T) {}
214     require_unsigned(&Wrapping(42_u32));
215 }
216 /*
217 // Commenting this out since it doesn't compile on Rust 1.8,
218 // because on this version Wrapping doesn't implement Neg and therefore can't
219 // implement Signed.
220 #[test]
221 fn signed_wrapping_is_signed() {
222     fn require_signed<T: Signed>(_: &T) {}
223     require_signed(&Wrapping(-42));
224 }
225 */
226