| 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 | } |
| 217 | |