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`.
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 i128);
76 
77 impl<T: Signed> Signed for Wrapping<T>
78 where
79     Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
80 {
81     #[inline]
abs(&self) -> Self82     fn abs(&self) -> Self {
83         Wrapping(self.0.abs())
84     }
85 
86     #[inline]
abs_sub(&self, other: &Self) -> Self87     fn abs_sub(&self, other: &Self) -> Self {
88         Wrapping(self.0.abs_sub(&other.0))
89     }
90 
91     #[inline]
signum(&self) -> Self92     fn signum(&self) -> Self {
93         Wrapping(self.0.signum())
94     }
95 
96     #[inline]
is_positive(&self) -> bool97     fn is_positive(&self) -> bool {
98         self.0.is_positive()
99     }
100 
101     #[inline]
is_negative(&self) -> bool102     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)]
abs<T: Signed>(value: T) -> T162 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)]
abs_sub<T: Signed>(x: T, y: T) -> T171 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)]
signum<T: Signed>(value: T) -> T189 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]
unsigned_wrapping_is_unsigned()207 fn unsigned_wrapping_is_unsigned() {
208     fn require_unsigned<T: Unsigned>(_: &T) {}
209     require_unsigned(&Wrapping(42_u32));
210 }
211 
212 #[test]
signed_wrapping_is_signed()213 fn signed_wrapping_is_signed() {
214     fn require_signed<T: Signed>(_: &T) {}
215     require_signed(&Wrapping(-42));
216 }
217