]> git.proxmox.com Git - rustc.git/blame - vendor/num-traits/src/sign.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / num-traits / src / sign.rs
CommitLineData
0531ce1d 1use core::num::Wrapping;
0731742a 2use core::ops::Neg;
8bb4bdeb 3
0531ce1d 4use float::FloatCore;
0731742a 5use Num;
8bb4bdeb
XL
6
7/// Useful functions for signed numbers (i.e. numbers that can be negative).
8pub 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
44macro_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
75signed_impl!(isize i8 i16 i32 i64);
76
8faf50e0
XL
77#[cfg(has_i128)]
78signed_impl!(i128);
79
0731742a
XL
80impl<T: Signed> Signed for Wrapping<T>
81where
82 Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
041b39d2
XL
83{
84 #[inline]
85 fn abs(&self) -> Self {
86 Wrapping(self.0.abs())
87 }
88
89 #[inline]
90 fn abs_sub(&self, other: &Self) -> Self {
91 Wrapping(self.0.abs_sub(&other.0))
92 }
93
94 #[inline]
95 fn signum(&self) -> Self {
96 Wrapping(self.0.signum())
97 }
98
99 #[inline]
0731742a
XL
100 fn is_positive(&self) -> bool {
101 self.0.is_positive()
102 }
041b39d2
XL
103
104 #[inline]
0731742a
XL
105 fn is_negative(&self) -> bool {
106 self.0.is_negative()
107 }
041b39d2
XL
108}
109
8bb4bdeb 110macro_rules! signed_float_impl {
0531ce1d 111 ($t:ty) => {
8bb4bdeb
XL
112 impl Signed for $t {
113 /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
114 #[inline]
115 fn abs(&self) -> $t {
0531ce1d 116 FloatCore::abs(*self)
8bb4bdeb
XL
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]
8bb4bdeb 123 fn abs_sub(&self, other: &$t) -> $t {
0731742a
XL
124 if *self <= *other {
125 0.
126 } else {
127 *self - *other
128 }
8bb4bdeb
XL
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 {
0531ce1d 138 FloatCore::signum(*self)
8bb4bdeb
XL
139 }
140
141 /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
142 #[inline]
0731742a
XL
143 fn is_positive(&self) -> bool {
144 FloatCore::is_sign_positive(*self)
145 }
8bb4bdeb
XL
146
147 /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
148 #[inline]
0731742a
XL
149 fn is_negative(&self) -> bool {
150 FloatCore::is_sign_negative(*self)
151 }
8bb4bdeb 152 }
0731742a 153 };
8bb4bdeb
XL
154}
155
0531ce1d
XL
156signed_float_impl!(f32);
157signed_float_impl!(f64);
8bb4bdeb
XL
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)]
165pub 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)]
174pub 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
0731742a
XL
191#[inline(always)]
192pub fn signum<T: Signed>(value: T) -> T {
193 value.signum()
194}
8bb4bdeb
XL
195
196/// A trait for values which cannot be negative
197pub trait Unsigned: Num {}
198
199macro_rules! empty_trait_impl {
200 ($name:ident for $($t:ty)*) => ($(
201 impl $name for $t {}
202 )*)
203}
204
205empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
8faf50e0
XL
206#[cfg(has_i128)]
207empty_trait_impl!(Unsigned for u128);
041b39d2 208
f035d41b 209impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}
041b39d2
XL
210
211#[test]
212fn unsigned_wrapping_is_unsigned() {
213 fn require_unsigned<T: Unsigned>(_: &T) {}
214 require_unsigned(&Wrapping(42_u32));
215}
5869c6ff 216
041b39d2
XL
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.
5869c6ff
XL
220// #[test]
221// fn signed_wrapping_is_signed() {
222// fn require_signed<T: Signed>(_: &T) {}
223// require_signed(&Wrapping(-42));
224// }