sign.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. use std::ops::Neg;
  2. use std::{f32, f64};
  3. use Num;
  4. /// Useful functions for signed numbers (i.e. numbers that can be negative).
  5. pub trait Signed: Sized + Num + Neg<Output = Self> {
  6. /// Computes the absolute value.
  7. ///
  8. /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
  9. ///
  10. /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
  11. fn abs(&self) -> Self;
  12. /// The positive difference of two numbers.
  13. ///
  14. /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
  15. /// between `self` and `other` is returned.
  16. fn abs_sub(&self, other: &Self) -> Self;
  17. /// Returns the sign of the number.
  18. ///
  19. /// For `f32` and `f64`:
  20. ///
  21. /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
  22. /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  23. /// * `NaN` if the number is `NaN`
  24. ///
  25. /// For signed integers:
  26. ///
  27. /// * `0` if the number is zero
  28. /// * `1` if the number is positive
  29. /// * `-1` if the number is negative
  30. fn signum(&self) -> Self;
  31. /// Returns true if the number is positive and false if the number is zero or negative.
  32. fn is_positive(&self) -> bool;
  33. /// Returns true if the number is negative and false if the number is zero or positive.
  34. fn is_negative(&self) -> bool;
  35. }
  36. macro_rules! signed_impl {
  37. ($($t:ty)*) => ($(
  38. impl Signed for $t {
  39. #[inline]
  40. fn abs(&self) -> $t {
  41. if self.is_negative() { -*self } else { *self }
  42. }
  43. #[inline]
  44. fn abs_sub(&self, other: &$t) -> $t {
  45. if *self <= *other { 0 } else { *self - *other }
  46. }
  47. #[inline]
  48. fn signum(&self) -> $t {
  49. match *self {
  50. n if n > 0 => 1,
  51. 0 => 0,
  52. _ => -1,
  53. }
  54. }
  55. #[inline]
  56. fn is_positive(&self) -> bool { *self > 0 }
  57. #[inline]
  58. fn is_negative(&self) -> bool { *self < 0 }
  59. }
  60. )*)
  61. }
  62. signed_impl!(isize i8 i16 i32 i64);
  63. macro_rules! signed_float_impl {
  64. ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
  65. impl Signed for $t {
  66. /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
  67. #[inline]
  68. fn abs(&self) -> $t {
  69. <$t>::abs(*self)
  70. }
  71. /// The positive difference of two numbers. Returns `0.0` if the number is
  72. /// less than or equal to `other`, otherwise the difference between`self`
  73. /// and `other` is returned.
  74. #[inline]
  75. #[allow(deprecated)]
  76. fn abs_sub(&self, other: &$t) -> $t {
  77. <$t>::abs_sub(*self, *other)
  78. }
  79. /// # Returns
  80. ///
  81. /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
  82. /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  83. /// - `NAN` if the number is NaN
  84. #[inline]
  85. fn signum(&self) -> $t {
  86. <$t>::signum(*self)
  87. }
  88. /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
  89. #[inline]
  90. fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }
  91. /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
  92. #[inline]
  93. fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
  94. }
  95. }
  96. }
  97. signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
  98. signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);
  99. /// Computes the absolute value.
  100. ///
  101. /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
  102. ///
  103. /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
  104. #[inline(always)]
  105. pub fn abs<T: Signed>(value: T) -> T {
  106. value.abs()
  107. }
  108. /// The positive difference of two numbers.
  109. ///
  110. /// Returns zero if `x` is less than or equal to `y`, otherwise the difference
  111. /// between `x` and `y` is returned.
  112. #[inline(always)]
  113. pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
  114. x.abs_sub(&y)
  115. }
  116. /// Returns the sign of the number.
  117. ///
  118. /// For `f32` and `f64`:
  119. ///
  120. /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
  121. /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
  122. /// * `NaN` if the number is `NaN`
  123. ///
  124. /// For signed integers:
  125. ///
  126. /// * `0` if the number is zero
  127. /// * `1` if the number is positive
  128. /// * `-1` if the number is negative
  129. #[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
  130. /// A trait for values which cannot be negative
  131. pub trait Unsigned: Num {}
  132. macro_rules! empty_trait_impl {
  133. ($name:ident for $($t:ty)*) => ($(
  134. impl $name for $t {}
  135. )*)
  136. }
  137. empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);