sign.rs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. use core::ops::Neg;
  2. use core::{f32, f64};
  3. use core::num::Wrapping;
  4. use Num;
  5. /// Useful functions for signed numbers (i.e. numbers that can be negative).
  6. pub trait Signed: Sized + Num + Neg<Output = Self> {
  7. /// Computes the absolute value.
  8. ///
  9. /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
  10. ///
  11. /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
  12. fn abs(&self) -> Self;
  13. /// The positive difference of two numbers.
  14. ///
  15. /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
  16. /// between `self` and `other` is returned.
  17. fn abs_sub(&self, other: &Self) -> Self;
  18. /// Returns the sign of the number.
  19. ///
  20. /// For `f32` and `f64`:
  21. ///
  22. /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
  23. /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  24. /// * `NaN` if the number is `NaN`
  25. ///
  26. /// For signed integers:
  27. ///
  28. /// * `0` if the number is zero
  29. /// * `1` if the number is positive
  30. /// * `-1` if the number is negative
  31. fn signum(&self) -> Self;
  32. /// Returns true if the number is positive and false if the number is zero or negative.
  33. fn is_positive(&self) -> bool;
  34. /// Returns true if the number is negative and false if the number is zero or positive.
  35. fn is_negative(&self) -> bool;
  36. }
  37. macro_rules! signed_impl {
  38. ($($t:ty)*) => ($(
  39. impl Signed for $t {
  40. #[inline]
  41. fn abs(&self) -> $t {
  42. if self.is_negative() { -*self } else { *self }
  43. }
  44. #[inline]
  45. fn abs_sub(&self, other: &$t) -> $t {
  46. if *self <= *other { 0 } else { *self - *other }
  47. }
  48. #[inline]
  49. fn signum(&self) -> $t {
  50. match *self {
  51. n if n > 0 => 1,
  52. 0 => 0,
  53. _ => -1,
  54. }
  55. }
  56. #[inline]
  57. fn is_positive(&self) -> bool { *self > 0 }
  58. #[inline]
  59. fn is_negative(&self) -> bool { *self < 0 }
  60. }
  61. )*)
  62. }
  63. signed_impl!(isize i8 i16 i32 i64);
  64. impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
  65. {
  66. #[inline]
  67. fn abs(&self) -> Self {
  68. Wrapping(self.0.abs())
  69. }
  70. #[inline]
  71. fn abs_sub(&self, other: &Self) -> Self {
  72. Wrapping(self.0.abs_sub(&other.0))
  73. }
  74. #[inline]
  75. fn signum(&self) -> Self {
  76. Wrapping(self.0.signum())
  77. }
  78. #[inline]
  79. fn is_positive(&self) -> bool { self.0.is_positive() }
  80. #[inline]
  81. fn is_negative(&self) -> bool { self.0.is_negative() }
  82. }
  83. macro_rules! signed_float_impl {
  84. ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
  85. impl Signed for $t {
  86. /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
  87. #[inline]
  88. #[cfg(feature = "std")]
  89. fn abs(&self) -> $t {
  90. (*self).abs()
  91. }
  92. /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
  93. #[inline]
  94. #[cfg(not(feature = "std"))]
  95. fn abs(&self) -> $t {
  96. if self.is_positive() {
  97. *self
  98. } else if self.is_negative() {
  99. -*self
  100. } else {
  101. $nan
  102. }
  103. }
  104. /// The positive difference of two numbers. Returns `0.0` if the number is
  105. /// less than or equal to `other`, otherwise the difference between`self`
  106. /// and `other` is returned.
  107. #[inline]
  108. fn abs_sub(&self, other: &$t) -> $t {
  109. if *self <= *other { 0. } else { *self - *other }
  110. }
  111. /// # Returns
  112. ///
  113. /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
  114. /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  115. /// - `NAN` if the number is NaN
  116. #[inline]
  117. #[cfg(feature = "std")]
  118. fn signum(&self) -> $t {
  119. use Float;
  120. Float::signum(*self)
  121. }
  122. /// # Returns
  123. ///
  124. /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
  125. /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  126. /// - `NAN` if the number is NaN
  127. #[inline]
  128. #[cfg(not(feature = "std"))]
  129. fn signum(&self) -> $t {
  130. if self.is_positive() {
  131. 1.0
  132. } else if self.is_negative() {
  133. -1.0
  134. } else {
  135. $nan
  136. }
  137. }
  138. /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
  139. #[inline]
  140. fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }
  141. /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
  142. #[inline]
  143. fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
  144. }
  145. }
  146. }
  147. signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
  148. signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);
  149. /// Computes the absolute value.
  150. ///
  151. /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
  152. ///
  153. /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
  154. #[inline(always)]
  155. pub fn abs<T: Signed>(value: T) -> T {
  156. value.abs()
  157. }
  158. /// The positive difference of two numbers.
  159. ///
  160. /// Returns zero if `x` is less than or equal to `y`, otherwise the difference
  161. /// between `x` and `y` is returned.
  162. #[inline(always)]
  163. pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
  164. x.abs_sub(&y)
  165. }
  166. /// Returns the sign of the number.
  167. ///
  168. /// For `f32` and `f64`:
  169. ///
  170. /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
  171. /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  172. /// * `NaN` if the number is `NaN`
  173. ///
  174. /// For signed integers:
  175. ///
  176. /// * `0` if the number is zero
  177. /// * `1` if the number is positive
  178. /// * `-1` if the number is negative
  179. #[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
  180. /// A trait for values which cannot be negative
  181. pub trait Unsigned: Num {}
  182. macro_rules! empty_trait_impl {
  183. ($name:ident for $($t:ty)*) => ($(
  184. impl $name for $t {}
  185. )*)
  186. }
  187. empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
  188. impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}
  189. #[test]
  190. fn unsigned_wrapping_is_unsigned() {
  191. fn require_unsigned<T: Unsigned>(_: &T) {}
  192. require_unsigned(&Wrapping(42_u32));
  193. }
  194. /*
  195. // Commenting this out since it doesn't compile on Rust 1.8,
  196. // because on this version Wrapping doesn't implement Neg and therefore can't
  197. // implement Signed.
  198. #[test]
  199. fn signed_wrapping_is_signed() {
  200. fn require_signed<T: Signed>(_: &T) {}
  201. require_signed(&Wrapping(-42));
  202. }
  203. */