]> git.proxmox.com Git - rustc.git/blob - vendor/num-traits/src/sign.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / vendor / num-traits / src / sign.rs
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 }