1use core::num::Wrapping;
2use core::ops::Neg;
34use crate::float::FloatCore;
5use crate::Num;
67/// 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`.
14fn abs(&self) -> Self;
1516/// 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.
20fn abs_sub(&self, other: &Self) -> Self;
2122/// 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
35fn signum(&self) -> Self;
3637/// Returns true if the number is positive and false if the number is zero or negative.
38fn is_positive(&self) -> bool;
3940/// Returns true if the number is negative and false if the number is zero or positive.
41fn is_negative(&self) -> bool;
42}
4344macro_rules! signed_impl {
45 ($($t:ty)*) => ($(
46impl Signed for $t {
47#[inline]
48fn abs(&self) -> $t {
49if self.is_negative() { -*self } else { *self }
50 }
5152#[inline]
53fn abs_sub(&self, other: &$t) -> $t {
54if *self <= *other { 0 } else { *self - *other }
55 }
5657#[inline]
58fn signum(&self) -> $t {
59match *self {
60 n if n > 0 => 1,
610 => 0,
62_ => -1,
63 }
64 }
6566#[inline]
67fn is_positive(&self) -> bool { *self > 0 }
6869#[inline]
70fn is_negative(&self) -> bool { *self < 0 }
71 }
72 )*)
73}
7475impl Signed for i128 {
#[inline]
fn abs(&self) -> i128 { if self.is_negative() { -*self } else { *self } }
#[inline]
fn abs_sub(&self, other: &i128) -> i128 {
if *self <= *other { 0 } else { *self - *other }
}
#[inline]
fn signum(&self) -> i128 {
match *self { n if n > 0 => 1, 0 => 0, _ => -1, }
}
#[inline]
fn is_positive(&self) -> bool { *self > 0 }
#[inline]
fn is_negative(&self) -> bool { *self < 0 }
}signed_impl!(isizei8i16i32i64i128);
7677impl<T: Signed> Signedfor Wrapping<T>
78where
79Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
80{
81#[inline]
82fn abs(&self) -> Self {
83Wrapping(self.0.abs())
84 }
8586#[inline]
87fn abs_sub(&self, other: &Self) -> Self {
88Wrapping(self.0.abs_sub(&other.0))
89 }
9091#[inline]
92fn signum(&self) -> Self {
93Wrapping(self.0.signum())
94 }
9596#[inline]
97fn is_positive(&self) -> bool {
98self.0.is_positive()
99 }
100101#[inline]
102fn is_negative(&self) -> bool {
103self.0.is_negative()
104 }
105}
106107macro_rules! signed_float_impl {
108 ($t:ty) => {
109impl Signed for $t {
110/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
111#[inline]
112fn abs(&self) -> $t {
113 FloatCore::abs(*self)
114 }
115116/// 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]
120fn abs_sub(&self, other: &$t) -> $t {
121if *self <= *other {
1220.
123} else {
124*self - *other
125 }
126 }
127128/// # 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]
134fn signum(&self) -> $t {
135 FloatCore::signum(*self)
136 }
137138/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
139#[inline]
140fn is_positive(&self) -> bool {
141 FloatCore::is_sign_positive(*self)
142 }
143144/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
145#[inline]
146fn is_negative(&self) -> bool {
147 FloatCore::is_sign_negative(*self)
148 }
149 }
150 };
151}
152153impl Signed for f32 {
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
#[inline]
fn abs(&self) -> f32 { FloatCore::abs(*self) }
/// The positive difference of two numbers. Returns `0.0` if the number is
/// less than or equal to `other`, otherwise the difference between`self`
/// and `other` is returned.
#[inline]
fn abs_sub(&self, other: &f32) -> f32 {
if *self <= *other { 0. } else { *self - *other }
}
/// # Returns
///
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// - `NAN` if the number is NaN
#[inline]
fn signum(&self) -> f32 { FloatCore::signum(*self) }
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
#[inline]
fn is_positive(&self) -> bool { FloatCore::is_sign_positive(*self) }
/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
#[inline]
fn is_negative(&self) -> bool { FloatCore::is_sign_negative(*self) }
}signed_float_impl!(f32);
154impl Signed for f64 {
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
#[inline]
fn abs(&self) -> f64 { FloatCore::abs(*self) }
/// The positive difference of two numbers. Returns `0.0` if the number is
/// less than or equal to `other`, otherwise the difference between`self`
/// and `other` is returned.
#[inline]
fn abs_sub(&self, other: &f64) -> f64 {
if *self <= *other { 0. } else { *self - *other }
}
/// # Returns
///
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// - `NAN` if the number is NaN
#[inline]
fn signum(&self) -> f64 { FloatCore::signum(*self) }
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
#[inline]
fn is_positive(&self) -> bool { FloatCore::is_sign_positive(*self) }
/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
#[inline]
fn is_negative(&self) -> bool { FloatCore::is_sign_negative(*self) }
}signed_float_impl!(f64);
155156/// 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)]
162pub fn abs<T: Signed>(value: T) -> T {
163value.abs()
164}
165166/// 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)]
171pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
172x.abs_sub(&y)
173}
174175/// 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)]
189pub fn signum<T: Signed>(value: T) -> T {
190value.signum()
191}
192193/// A trait for values which cannot be negative
194pub trait Unsigned: Num {}
195196macro_rules! empty_trait_impl {
197 ($name:ident for $($t:ty)*) => ($(
198impl $name for $t {}
199 )*)
200}
201202impl Unsigned for u128 {}empty_trait_impl!(Unsigned for usizeu8u16u32u64u128);
203204impl<T: Unsigned> Unsignedfor Wrapping<T> where Wrapping<T>: Num {}
205206#[test]
207fn unsigned_wrapping_is_unsigned() {
208fn require_unsigned<T: Unsigned>(_: &T) {}
209 require_unsigned(&Wrapping(42_u32));
210}
211212#[test]
213fn signed_wrapping_is_signed() {
214fn require_signed<T: Signed>(_: &T) {}
215 require_signed(&Wrapping(-42));
216}