diff options
Diffstat (limited to 'vendor/num-traits/src')
-rw-r--r-- | vendor/num-traits/src/bounds.rs | 30 | ||||
-rw-r--r-- | vendor/num-traits/src/cast.rs | 76 | ||||
-rw-r--r-- | vendor/num-traits/src/float.rs | 459 | ||||
-rw-r--r-- | vendor/num-traits/src/int.rs | 159 | ||||
-rw-r--r-- | vendor/num-traits/src/lib.rs | 100 | ||||
-rw-r--r-- | vendor/num-traits/src/macros.rs | 9 | ||||
-rw-r--r-- | vendor/num-traits/src/ops/euclid.rs | 347 | ||||
-rw-r--r-- | vendor/num-traits/src/ops/mod.rs | 2 | ||||
-rw-r--r-- | vendor/num-traits/src/ops/overflowing.rs | 104 | ||||
-rw-r--r-- | vendor/num-traits/src/sign.rs | 13 |
10 files changed, 995 insertions, 304 deletions
diff --git a/vendor/num-traits/src/bounds.rs b/vendor/num-traits/src/bounds.rs index c9ff749d2..36e1bbdfb 100644 --- a/vendor/num-traits/src/bounds.rs +++ b/vendor/num-traits/src/bounds.rs @@ -8,12 +8,38 @@ use core::{u16, u32, u64, u8, usize}; /// Numbers which have upper and lower bounds pub trait Bounded { // FIXME (#5527): These should be associated constants - /// returns the smallest finite number this type can represent + /// Returns the smallest finite number this type can represent fn min_value() -> Self; - /// returns the largest finite number this type can represent + /// Returns the largest finite number this type can represent fn max_value() -> Self; } +/// Numbers which have lower bounds +pub trait LowerBounded { + /// Returns the smallest finite number this type can represent + fn min_value() -> Self; +} + +// FIXME: With a major version bump, this should be a supertrait instead +impl<T: Bounded> LowerBounded for T { + fn min_value() -> T { + Bounded::min_value() + } +} + +/// Numbers which have upper bounds +pub trait UpperBounded { + /// Returns the largest finite number this type can represent + fn max_value() -> Self; +} + +// FIXME: With a major version bump, this should be a supertrait instead +impl<T: Bounded> UpperBounded for T { + fn max_value() -> T { + Bounded::max_value() + } +} + macro_rules! bounded_impl { ($t:ty, $min:expr, $max:expr) => { impl Bounded for $t { diff --git a/vendor/num-traits/src/cast.rs b/vendor/num-traits/src/cast.rs index b33f1a19f..d38c33815 100644 --- a/vendor/num-traits/src/cast.rs +++ b/vendor/num-traits/src/cast.rs @@ -6,9 +6,16 @@ use core::{i128, u128}; use core::{i16, i32, i64, i8, isize}; use core::{u16, u32, u64, u8, usize}; -use float::FloatCore; - /// A generic trait for converting a value to a number. +/// +/// A value can be represented by the target type when it lies within +/// the range of scalars supported by the target type. +/// For example, a negative integer cannot be represented by an unsigned +/// integer type, and an `i64` with a very high magnitude might not be +/// convertible to an `i32`. +/// On the other hand, conversions with possible precision loss or truncation +/// are admitted, like an `f32` with a decimal part to an integer type, or +/// even a large `f64` saturating to `f32` infinity. pub trait ToPrimitive { /// Converts the value of `self` to an `isize`. If the value cannot be /// represented by an `isize`, then `None` is returned. @@ -94,7 +101,7 @@ pub trait ToPrimitive { /// /// This method is only available with feature `i128` enabled on Rust >= 1.26. /// - /// The default implementation converts through `to_u64()`. Types implementing + /// The default implementation converts through `to_u64()`. Types implementing /// this trait should override this method if they can represent a greater range. #[inline] #[cfg(has_i128)] @@ -102,15 +109,21 @@ pub trait ToPrimitive { self.to_u64().map(From::from) } - /// Converts the value of `self` to an `f32`. If the value cannot be - /// represented by an `f32`, then `None` is returned. + /// Converts the value of `self` to an `f32`. Overflows may map to positive + /// or negative inifinity, otherwise `None` is returned if the value cannot + /// be represented by an `f32`. #[inline] fn to_f32(&self) -> Option<f32> { self.to_f64().as_ref().and_then(ToPrimitive::to_f32) } - /// Converts the value of `self` to an `f64`. If the value cannot be - /// represented by an `f64`, then `None` is returned. + /// Converts the value of `self` to an `f64`. Overflows may map to positive + /// or negative inifinity, otherwise `None` is returned if the value cannot + /// be represented by an `f64`. + /// + /// The default implementation tries to convert through `to_i64()`, and + /// failing that through `to_u64()`. Types implementing this trait should + /// override this method if they can represent a greater range. #[inline] fn to_f64(&self) -> Option<f64> { match self.to_i64() { @@ -271,14 +284,8 @@ macro_rules! impl_to_primitive_float_to_float { ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$( #[inline] fn $method(&self) -> Option<$DstT> { - // Only finite values that are reducing size need to worry about overflow. - if size_of::<$SrcT>() > size_of::<$DstT>() && FloatCore::is_finite(*self) { - let n = *self as f64; - if n < $DstT::MIN as f64 || n > $DstT::MAX as f64 { - return None; - } - } - // We can safely cast NaN, +-inf, and finite values in range. + // We can safely cast all values, whether NaN, +-inf, or finite. + // Finite values that are reducing size may saturate to +-inf. Some(*self as $DstT) } )*} @@ -392,6 +399,15 @@ impl_to_primitive_float!(f32); impl_to_primitive_float!(f64); /// A generic trait for converting a number to a value. +/// +/// A value can be represented by the target type when it lies within +/// the range of scalars supported by the target type. +/// For example, a negative integer cannot be represented by an unsigned +/// integer type, and an `i64` with a very high magnitude might not be +/// convertible to an `i32`. +/// On the other hand, conversions with possible precision loss or truncation +/// are admitted, like an `f32` with a decimal part to an integer type, or +/// even a large `f64` saturating to `f32` infinity. pub trait FromPrimitive: Sized { /// Converts an `isize` to return an optional value of this type. If the /// value cannot be represented by this type, then `None` is returned. @@ -492,6 +508,10 @@ pub trait FromPrimitive: Sized { /// Converts a `f64` to return an optional value of this type. If the /// value cannot be represented by this type, then `None` is returned. + /// + /// The default implementation tries to convert through `from_i64()`, and + /// failing that through `from_u64()`. Types implementing this trait should + /// override this method if they can represent a greater range. #[inline] fn from_f64(n: f64) -> Option<Self> { match n.to_i64() { @@ -672,6 +692,15 @@ pub trait NumCast: Sized + ToPrimitive { /// Creates a number from another value that can be converted into /// a primitive via the `ToPrimitive` trait. If the source value cannot be /// represented by the target type, then `None` is returned. + /// + /// A value can be represented by the target type when it lies within + /// the range of scalars supported by the target type. + /// For example, a negative integer cannot be represented by an unsigned + /// integer type, and an `i64` with a very high magnitude might not be + /// convertible to an `i32`. + /// On the other hand, conversions with possible precision loss or truncation + /// are admitted, like an `f32` with a decimal part to an integer type, or + /// even a large `f64` saturating to `f32` infinity. fn from<T: ToPrimitive>(n: T) -> Option<Self>; } @@ -728,25 +757,16 @@ impl<T: NumCast> NumCast for Wrapping<T> { /// /// # Safety /// -/// Currently, some uses of the `as` operator are not entirely safe. -/// In particular, it is undefined behavior if: -/// -/// - A truncated floating point value cannot fit in the target integer -/// type ([#10184](https://github.com/rust-lang/rust/issues/10184)); +/// **In Rust versions before 1.45.0**, some uses of the `as` operator were not entirely safe. +/// In particular, it was undefined behavior if +/// a truncated floating point value could not fit in the target integer +/// type ([#10184](https://github.com/rust-lang/rust/issues/10184)). /// /// ```ignore /// # use num_traits::AsPrimitive; /// let x: u8 = (1.04E+17).as_(); // UB /// ``` /// -/// - Or a floating point value does not fit in another floating -/// point type ([#15536](https://github.com/rust-lang/rust/issues/15536)). -/// -/// ```ignore -/// # use num_traits::AsPrimitive; -/// let x: f32 = (1e300f64).as_(); // UB -/// ``` -/// pub trait AsPrimitive<T>: 'static + Copy where T: 'static + Copy, diff --git a/vendor/num-traits/src/float.rs b/vendor/num-traits/src/float.rs index 0e7b9db35..47bd65431 100644 --- a/vendor/num-traits/src/float.rs +++ b/vendor/num-traits/src/float.rs @@ -783,6 +783,17 @@ impl FloatCore for f32 { #[inline] #[cfg(not(feature = "std"))] + fn is_sign_negative(self) -> bool { + const SIGN_MASK: u32 = 0x80000000; + + // Safety: this identical to the implementation of f32::to_bits(), + // which is only available starting at Rust 1.20 + let bits: u32 = unsafe { mem::transmute(self) }; + bits & SIGN_MASK != 0 + } + + #[inline] + #[cfg(not(feature = "std"))] fn to_degrees(self) -> Self { // Use a constant for better precision. const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; @@ -818,6 +829,23 @@ impl FloatCore for f32 { Self::to_degrees(self) -> Self; Self::to_radians(self) -> Self; } + + #[cfg(all(not(feature = "std"), feature = "libm"))] + forward! { + libm::floorf as floor(self) -> Self; + libm::ceilf as ceil(self) -> Self; + libm::roundf as round(self) -> Self; + libm::truncf as trunc(self) -> Self; + libm::fabsf as abs(self) -> Self; + libm::fminf as min(self, other: Self) -> Self; + libm::fmaxf as max(self, other: Self) -> Self; + } + + #[cfg(all(not(feature = "std"), feature = "libm"))] + #[inline] + fn fract(self) -> Self { + self - libm::truncf(self) + } } impl FloatCore for f64 { @@ -857,6 +885,17 @@ impl FloatCore for f64 { #[inline] #[cfg(not(feature = "std"))] + fn is_sign_negative(self) -> bool { + const SIGN_MASK: u64 = 0x8000000000000000; + + // Safety: this identical to the implementation of f64::to_bits(), + // which is only available starting at Rust 1.20 + let bits: u64 = unsafe { mem::transmute(self) }; + bits & SIGN_MASK != 0 + } + + #[inline] + #[cfg(not(feature = "std"))] fn to_degrees(self) -> Self { // The division here is correctly rounded with respect to the true // value of 180/π. (This differs from f32, where a constant must be @@ -893,6 +932,23 @@ impl FloatCore for f64 { Self::to_degrees(self) -> Self; Self::to_radians(self) -> Self; } + + #[cfg(all(not(feature = "std"), feature = "libm"))] + forward! { + libm::floor as floor(self) -> Self; + libm::ceil as ceil(self) -> Self; + libm::round as round(self) -> Self; + libm::trunc as trunc(self) -> Self; + libm::fabs as abs(self) -> Self; + libm::fmin as min(self, other: Self) -> Self; + libm::fmax as max(self, other: Self) -> Self; + } + + #[cfg(all(not(feature = "std"), feature = "libm"))] + #[inline] + fn fract(self) -> Self { + self - libm::trunc(self) + } } // FIXME: these doctests aren't actually helpful, because they're using and @@ -1806,6 +1862,35 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> { /// assert!(abs_difference < 1e-10); /// ``` fn integer_decode(self) -> (u64, i16, i8); + + /// Returns a number composed of the magnitude of `self` and the sign of + /// `sign`. + /// + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise + /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of + /// `sign` is returned. + /// + /// # Examples + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 3.5_f32; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f32); + /// assert_eq!(f.copysign(-0.42), -3.5_f32); + /// assert_eq!((-f).copysign(0.42), 3.5_f32); + /// assert_eq!((-f).copysign(-0.42), -3.5_f32); + /// + /// assert!(f32::nan().copysign(1.0).is_nan()); + /// ``` + fn copysign(self, sign: Self) -> Self { + if self.is_sign_negative() == sign.is_sign_negative() { + self + } else { + self.neg() + } + } } #[cfg(feature = "std")] @@ -1883,6 +1968,12 @@ macro_rules! float_impl_std { Self::acosh(self) -> Self; Self::atanh(self) -> Self; } + + #[cfg(has_copysign)] + #[inline] + fn copysign(self, sign: Self) -> Self { + Self::copysign(self, sign) + } } }; } @@ -1908,7 +1999,7 @@ macro_rules! float_impl_libm { #[inline] fn fract(self) -> Self { - self - FloatCore::trunc(self) + self - Float::trunc(self) } #[inline] @@ -1929,8 +2020,6 @@ macro_rules! float_impl_libm { FloatCore::powi(self, n: i32) -> Self; FloatCore::to_degrees(self) -> Self; FloatCore::to_radians(self) -> Self; - FloatCore::max(self, other: Self) -> Self; - FloatCore::min(self, other: Self) -> Self; } }; } @@ -1981,129 +2070,42 @@ impl Float for f32 { fn abs_sub(self, other: Self) -> Self { libm::fdimf(self, other) } - #[inline] - fn floor(self) -> Self { - libm::floorf(self) - } - #[inline] - fn ceil(self) -> Self { - libm::ceilf(self) - } - #[inline] - fn round(self) -> Self { - libm::roundf(self) - } - #[inline] - fn trunc(self) -> Self { - libm::truncf(self) - } - #[inline] - fn abs(self) -> Self { - libm::fabsf(self) - } - #[inline] - fn mul_add(self, a: Self, b: Self) -> Self { - libm::fmaf(self, a, b) - } - #[inline] - fn powf(self, n: Self) -> Self { - libm::powf(self, n) - } - #[inline] - fn sqrt(self) -> Self { - libm::sqrtf(self) - } - #[inline] - fn exp(self) -> Self { - libm::expf(self) - } - #[inline] - fn exp2(self) -> Self { - libm::exp2f(self) - } - #[inline] - fn ln(self) -> Self { - libm::logf(self) - } - #[inline] - fn log2(self) -> Self { - libm::log2f(self) - } - #[inline] - fn log10(self) -> Self { - libm::log10f(self) - } - #[inline] - fn cbrt(self) -> Self { - libm::cbrtf(self) - } - #[inline] - fn hypot(self, other: Self) -> Self { - libm::hypotf(self, other) - } - #[inline] - fn sin(self) -> Self { - libm::sinf(self) - } - #[inline] - fn cos(self) -> Self { - libm::cosf(self) - } - #[inline] - fn tan(self) -> Self { - libm::tanf(self) - } - #[inline] - fn asin(self) -> Self { - libm::asinf(self) - } - #[inline] - fn acos(self) -> Self { - libm::acosf(self) - } - #[inline] - fn atan(self) -> Self { - libm::atanf(self) - } - #[inline] - fn atan2(self, other: Self) -> Self { - libm::atan2f(self, other) - } - #[inline] - fn sin_cos(self) -> (Self, Self) { - libm::sincosf(self) - } - #[inline] - fn exp_m1(self) -> Self { - libm::expm1f(self) - } - #[inline] - fn ln_1p(self) -> Self { - libm::log1pf(self) - } - #[inline] - fn sinh(self) -> Self { - libm::sinhf(self) - } - #[inline] - fn cosh(self) -> Self { - libm::coshf(self) - } - #[inline] - fn tanh(self) -> Self { - libm::tanhf(self) - } - #[inline] - fn asinh(self) -> Self { - libm::asinhf(self) - } - #[inline] - fn acosh(self) -> Self { - libm::acoshf(self) - } - #[inline] - fn atanh(self) -> Self { - libm::atanhf(self) + + forward! { + libm::floorf as floor(self) -> Self; + libm::ceilf as ceil(self) -> Self; + libm::roundf as round(self) -> Self; + libm::truncf as trunc(self) -> Self; + libm::fabsf as abs(self) -> Self; + libm::fmaf as mul_add(self, a: Self, b: Self) -> Self; + libm::powf as powf(self, n: Self) -> Self; + libm::sqrtf as sqrt(self) -> Self; + libm::expf as exp(self) -> Self; + libm::exp2f as exp2(self) -> Self; + libm::logf as ln(self) -> Self; + libm::log2f as log2(self) -> Self; + libm::log10f as log10(self) -> Self; + libm::cbrtf as cbrt(self) -> Self; + libm::hypotf as hypot(self, other: Self) -> Self; + libm::sinf as sin(self) -> Self; + libm::cosf as cos(self) -> Self; + libm::tanf as tan(self) -> Self; + libm::asinf as asin(self) -> Self; + libm::acosf as acos(self) -> Self; + libm::atanf as atan(self) -> Self; + libm::atan2f as atan2(self, other: Self) -> Self; + libm::sincosf as sin_cos(self) -> (Self, Self); + libm::expm1f as exp_m1(self) -> Self; + libm::log1pf as ln_1p(self) -> Self; + libm::sinhf as sinh(self) -> Self; + libm::coshf as cosh(self) -> Self; + libm::tanhf as tanh(self) -> Self; + libm::asinhf as asinh(self) -> Self; + libm::acoshf as acosh(self) -> Self; + libm::atanhf as atanh(self) -> Self; + libm::fmaxf as max(self, other: Self) -> Self; + libm::fminf as min(self, other: Self) -> Self; + libm::copysignf as copysign(self, other: Self) -> Self; } } @@ -2116,129 +2118,42 @@ impl Float for f64 { fn abs_sub(self, other: Self) -> Self { libm::fdim(self, other) } - #[inline] - fn floor(self) -> Self { - libm::floor(self) - } - #[inline] - fn ceil(self) -> Self { - libm::ceil(self) - } - #[inline] - fn round(self) -> Self { - libm::round(self) - } - #[inline] - fn trunc(self) -> Self { - libm::trunc(self) - } - #[inline] - fn abs(self) -> Self { - libm::fabs(self) - } - #[inline] - fn mul_add(self, a: Self, b: Self) -> Self { - libm::fma(self, a, b) - } - #[inline] - fn powf(self, n: Self) -> Self { - libm::pow(self, n) - } - #[inline] - fn sqrt(self) -> Self { - libm::sqrt(self) - } - #[inline] - fn exp(self) -> Self { - libm::exp(self) - } - #[inline] - fn exp2(self) -> Self { - libm::exp2(self) - } - #[inline] - fn ln(self) -> Self { - libm::log(self) - } - #[inline] - fn log2(self) -> Self { - libm::log2(self) - } - #[inline] - fn log10(self) -> Self { - libm::log10(self) - } - #[inline] - fn cbrt(self) -> Self { - libm::cbrt(self) - } - #[inline] - fn hypot(self, other: Self) -> Self { - libm::hypot(self, other) - } - #[inline] - fn sin(self) -> Self { - libm::sin(self) - } - #[inline] - fn cos(self) -> Self { - libm::cos(self) - } - #[inline] - fn tan(self) -> Self { - libm::tan(self) - } - #[inline] - fn asin(self) -> Self { - libm::asin(self) - } - #[inline] - fn acos(self) -> Self { - libm::acos(self) - } - #[inline] - fn atan(self) -> Self { - libm::atan(self) - } - #[inline] - fn atan2(self, other: Self) -> Self { - libm::atan2(self, other) - } - #[inline] - fn sin_cos(self) -> (Self, Self) { - libm::sincos(self) - } - #[inline] - fn exp_m1(self) -> Self { - libm::expm1(self) - } - #[inline] - fn ln_1p(self) -> Self { - libm::log1p(self) - } - #[inline] - fn sinh(self) -> Self { - libm::sinh(self) - } - #[inline] - fn cosh(self) -> Self { - libm::cosh(self) - } - #[inline] - fn tanh(self) -> Self { - libm::tanh(self) - } - #[inline] - fn asinh(self) -> Self { - libm::asinh(self) - } - #[inline] - fn acosh(self) -> Self { - libm::acosh(self) - } - #[inline] - fn atanh(self) -> Self { - libm::atanh(self) + + forward! { + libm::floor as floor(self) -> Self; + libm::ceil as ceil(self) -> Self; + libm::round as round(self) -> Self; + libm::trunc as trunc(self) -> Self; + libm::fabs as abs(self) -> Self; + libm::fma as mul_add(self, a: Self, b: Self) -> Self; + libm::pow as powf(self, n: Self) -> Self; + libm::sqrt as sqrt(self) -> Self; + libm::exp as exp(self) -> Self; + libm::exp2 as exp2(self) -> Self; + libm::log as ln(self) -> Self; + libm::log2 as log2(self) -> Self; + libm::log10 as log10(self) -> Self; + libm::cbrt as cbrt(self) -> Self; + libm::hypot as hypot(self, other: Self) -> Self; + libm::sin as sin(self) -> Self; + libm::cos as cos(self) -> Self; + libm::tan as tan(self) -> Self; + libm::asin as asin(self) -> Self; + libm::acos as acos(self) -> Self; + libm::atan as atan(self) -> Self; + libm::atan2 as atan2(self, other: Self) -> Self; + libm::sincos as sin_cos(self) -> (Self, Self); + libm::expm1 as exp_m1(self) -> Self; + libm::log1p as ln_1p(self) -> Self; + libm::sinh as sinh(self) -> Self; + libm::cosh as cosh(self) -> Self; + libm::tanh as tanh(self) -> Self; + libm::asinh as asinh(self) -> Self; + libm::acosh as acosh(self) -> Self; + libm::atanh as atanh(self) -> Self; + libm::fmax as max(self, other: Self) -> Self; + libm::fmin as min(self, other: Self) -> Self; + libm::copysign as copysign(self, sign: Self) -> Self; } } @@ -2387,4 +2302,50 @@ mod tests { check::<f32>(1e-6); check::<f64>(1e-12); } + + #[test] + #[cfg(any(feature = "std", feature = "libm"))] + fn copysign() { + use float::Float; + test_copysign_generic(2.0_f32, -2.0_f32, f32::nan()); + test_copysign_generic(2.0_f64, -2.0_f64, f64::nan()); + test_copysignf(2.0_f32, -2.0_f32, f32::nan()); + } + + #[cfg(any(feature = "std", feature = "libm"))] + fn test_copysignf(p: f32, n: f32, nan: f32) { + use core::ops::Neg; + use float::Float; + + assert!(p.is_sign_positive()); + assert!(n.is_sign_negative()); + assert!(nan.is_nan()); + + assert_eq!(p, Float::copysign(p, p)); + assert_eq!(p.neg(), Float::copysign(p, n)); + + assert_eq!(n, Float::copysign(n, n)); + assert_eq!(n.neg(), Float::copysign(n, p)); + + // FIXME: is_sign... only works on NaN starting in Rust 1.20 + // assert!(Float::copysign(nan, p).is_sign_positive()); + // assert!(Float::copysign(nan, n).is_sign_negative()); + } + + #[cfg(any(feature = "std", feature = "libm"))] + fn test_copysign_generic<F: ::float::Float + ::core::fmt::Debug>(p: F, n: F, nan: F) { + assert!(p.is_sign_positive()); + assert!(n.is_sign_negative()); + assert!(nan.is_nan()); + + assert_eq!(p, p.copysign(p)); + assert_eq!(p.neg(), p.copysign(n)); + + assert_eq!(n, n.copysign(n)); + assert_eq!(n.neg(), n.copysign(p)); + + // FIXME: is_sign... only works on NaN starting in Rust 1.20 + // assert!(nan.copysign(p).is_sign_positive()); + // assert!(nan.copysign(n).is_sign_negative()); + } } diff --git a/vendor/num-traits/src/int.rs b/vendor/num-traits/src/int.rs index 10e751a9d..c7dbf1246 100644 --- a/vendor/num-traits/src/int.rs +++ b/vendor/num-traits/src/int.rs @@ -78,6 +78,22 @@ pub trait PrimInt: /// ``` fn count_zeros(self) -> u32; + /// Returns the number of leading ones in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0xF00Du16; + /// + /// assert_eq!(n.leading_ones(), 4); + /// ``` + fn leading_ones(self) -> u32 { + (!self).leading_zeros() + } + /// Returns the number of leading zeros in the binary representation /// of `self`. /// @@ -92,6 +108,22 @@ pub trait PrimInt: /// ``` fn leading_zeros(self) -> u32; + /// Returns the number of trailing ones in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0xBEEFu16; + /// + /// assert_eq!(n.trailing_ones(), 4); + /// ``` + fn trailing_ones(self) -> u32 { + (!self).trailing_zeros() + } + /// Returns the number of trailing zeros in the binary representation /// of `self`. /// @@ -218,6 +250,26 @@ pub trait PrimInt: /// ``` fn swap_bytes(self) -> Self; + /// Reverses the order of bits in the integer. + /// + /// The least significant bit becomes the most significant bit, second least-significant bit + /// becomes second most-significant bit, etc. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0x12345678u32; + /// let m = 0x1e6a2c48u32; + /// + /// assert_eq!(n.reverse_bits(), m); + /// assert_eq!(0u32.reverse_bits(), 0); + /// ``` + fn reverse_bits(self) -> Self { + reverse_bits_fallback(self) + } + /// Convert an integer from big endian to the target's endianness. /// /// On big endian this is a no-op. On little endian the bytes are swapped. @@ -306,6 +358,39 @@ pub trait PrimInt: fn pow(self, exp: u32) -> Self; } +fn one_per_byte<P: PrimInt>() -> P { + // i8, u8: return 0x01 + // i16, u16: return 0x0101 = (0x01 << 8) | 0x01 + // i32, u32: return 0x01010101 = (0x0101 << 16) | 0x0101 + // ... + let mut ret = P::one(); + let mut shift = 8; + let mut b = ret.count_zeros() >> 3; + while b != 0 { + ret = (ret << shift) | ret; + shift <<= 1; + b >>= 1; + } + ret +} + +fn reverse_bits_fallback<P: PrimInt>(i: P) -> P { + let rep_01: P = one_per_byte(); + let rep_03 = (rep_01 << 1) | rep_01; + let rep_05 = (rep_01 << 2) | rep_01; + let rep_0f = (rep_03 << 2) | rep_03; + let rep_33 = (rep_03 << 4) | rep_03; + let rep_55 = (rep_05 << 4) | rep_05; + + // code above only used to determine rep_0f, rep_33, rep_55; + // optimizer should be able to do it in compile time + let mut ret = i.swap_bytes(); + ret = ((ret & rep_0f) << 4) | ((ret >> 4) & rep_0f); + ret = ((ret & rep_33) << 2) | ((ret >> 2) & rep_33); + ret = ((ret & rep_55) << 1) | ((ret >> 1) & rep_55); + ret +} + macro_rules! prim_int_impl { ($T:ty, $S:ty, $U:ty) => { impl PrimInt for $T { @@ -319,11 +404,23 @@ macro_rules! prim_int_impl { <$T>::count_zeros(self) } + #[cfg(has_leading_trailing_ones)] + #[inline] + fn leading_ones(self) -> u32 { + <$T>::leading_ones(self) + } + #[inline] fn leading_zeros(self) -> u32 { <$T>::leading_zeros(self) } + #[cfg(has_leading_trailing_ones)] + #[inline] + fn trailing_ones(self) -> u32 { + <$T>::trailing_ones(self) + } + #[inline] fn trailing_zeros(self) -> u32 { <$T>::trailing_zeros(self) @@ -364,6 +461,12 @@ macro_rules! prim_int_impl { <$T>::swap_bytes(self) } + #[cfg(has_reverse_bits)] + #[inline] + fn reverse_bits(self) -> Self { + <$T>::reverse_bits(self) + } + #[inline] fn from_be(x: Self) -> Self { <$T>::from_be(x) @@ -407,3 +510,59 @@ prim_int_impl!(i64, i64, u64); #[cfg(has_i128)] prim_int_impl!(i128, i128, u128); prim_int_impl!(isize, isize, usize); + +#[cfg(test)] +mod tests { + use int::PrimInt; + + #[test] + pub fn reverse_bits() { + use core::{i16, i32, i64, i8}; + + assert_eq!( + PrimInt::reverse_bits(0x0123_4567_89ab_cdefu64), + 0xf7b3_d591_e6a2_c480 + ); + + assert_eq!(PrimInt::reverse_bits(0i8), 0); + assert_eq!(PrimInt::reverse_bits(-1i8), -1); + assert_eq!(PrimInt::reverse_bits(1i8), i8::MIN); + assert_eq!(PrimInt::reverse_bits(i8::MIN), 1); + assert_eq!(PrimInt::reverse_bits(-2i8), i8::MAX); + assert_eq!(PrimInt::reverse_bits(i8::MAX), -2); + + assert_eq!(PrimInt::reverse_bits(0i16), 0); + assert_eq!(PrimInt::reverse_bits(-1i16), -1); + assert_eq!(PrimInt::reverse_bits(1i16), i16::MIN); + assert_eq!(PrimInt::reverse_bits(i16::MIN), 1); + assert_eq!(PrimInt::reverse_bits(-2i16), i16::MAX); + assert_eq!(PrimInt::reverse_bits(i16::MAX), -2); + + assert_eq!(PrimInt::reverse_bits(0i32), 0); + assert_eq!(PrimInt::reverse_bits(-1i32), -1); + assert_eq!(PrimInt::reverse_bits(1i32), i32::MIN); + assert_eq!(PrimInt::reverse_bits(i32::MIN), 1); + assert_eq!(PrimInt::reverse_bits(-2i32), i32::MAX); + assert_eq!(PrimInt::reverse_bits(i32::MAX), -2); + + assert_eq!(PrimInt::reverse_bits(0i64), 0); + assert_eq!(PrimInt::reverse_bits(-1i64), -1); + assert_eq!(PrimInt::reverse_bits(1i64), i64::MIN); + assert_eq!(PrimInt::reverse_bits(i64::MIN), 1); + assert_eq!(PrimInt::reverse_bits(-2i64), i64::MAX); + assert_eq!(PrimInt::reverse_bits(i64::MAX), -2); + } + + #[test] + #[cfg(has_i128)] + pub fn reverse_bits_i128() { + use core::i128; + + assert_eq!(PrimInt::reverse_bits(0i128), 0); + assert_eq!(PrimInt::reverse_bits(-1i128), -1); + assert_eq!(PrimInt::reverse_bits(1i128), i128::MIN); + assert_eq!(PrimInt::reverse_bits(i128::MIN), 1); + assert_eq!(PrimInt::reverse_bits(-2i128), i128::MAX); + assert_eq!(PrimInt::reverse_bits(i128::MAX), -2); + } +} diff --git a/vendor/num-traits/src/lib.rs b/vendor/num-traits/src/lib.rs index d9989467e..bed87f366 100644 --- a/vendor/num-traits/src/lib.rs +++ b/vendor/num-traits/src/lib.rs @@ -40,6 +40,7 @@ pub use int::PrimInt; pub use ops::checked::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, }; +pub use ops::euclid::{CheckedEuclid, Euclid}; pub use ops::inv::Inv; pub use ops::mul_add::{MulAdd, MulAddAssign}; pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}; @@ -67,7 +68,7 @@ pub mod sign; pub trait Num: PartialEq + Zero + One + NumOps { type FromStrRadixErr; - /// Convert from a string and radix <= 36. + /// Convert from a string and radix (typically `2..=36`). /// /// # Examples /// @@ -80,10 +81,22 @@ pub trait Num: PartialEq + Zero + One + NumOps { /// let result = <i32 as Num>::from_str_radix("foo", 10); /// assert!(result.is_err()); /// ``` + /// + /// # Supported radices + /// + /// The exact range of supported radices is at the discretion of each type implementation. For + /// primitive integers, this is implemented by the inherent `from_str_radix` methods in the + /// standard library, which **panic** if the radix is not in the range from 2 to 36. The + /// implementation in this crate for primitive floats is similar. + /// + /// For third-party types, it is suggested that implementations should follow suit and at least + /// accept `2..=36` without panicking, but an `Err` may be returned for any unsupported radix. + /// It's possible that a type might not even support the common radix 10, nor any, if string + /// parsing doesn't make sense for that type. fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>; } -/// The trait for types implementing basic numeric operations +/// Generic trait for types implementing basic numeric operations /// /// This is automatically implemented for types which implement the operators. pub trait NumOps<Rhs = Self, Output = Self>: @@ -111,14 +124,16 @@ impl<T, Rhs, Output> NumOps<Rhs, Output> for T where pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {} -/// The trait for references which implement numeric operations, taking the +/// The trait for `Num` references which implement numeric operations, taking the /// second operand either by value or by reference. /// -/// This is automatically implemented for types which implement the operators. +/// This is automatically implemented for all types which implement the operators. It covers +/// every type implementing the operations though, regardless of it being a reference or +/// related to `Num`. pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {} impl<T, Base> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {} -/// The trait for types implementing numeric assignment operators (like `+=`). +/// Generic trait for types implementing numeric assignment operators (like `+=`). /// /// This is automatically implemented for types which implement the operators. pub trait NumAssignOps<Rhs = Self>: @@ -163,11 +178,7 @@ int_trait_impl!(Num for u128 i128); impl<T: Num> Num for Wrapping<T> where - Wrapping<T>: Add<Output = Wrapping<T>> - + Sub<Output = Wrapping<T>> - + Mul<Output = Wrapping<T>> - + Div<Output = Wrapping<T>> - + Rem<Output = Wrapping<T>>, + Wrapping<T>: NumOps, { type FromStrRadixErr = T::FromStrRadixErr; fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { @@ -198,6 +209,14 @@ impl fmt::Display for ParseFloatError { } } +fn str_to_ascii_lower_eq_str(a: &str, b: &str) -> bool { + a.len() == b.len() + && a.bytes().zip(b.bytes()).all(|(a, b)| { + let a_to_ascii_lower = a | (((b'A' <= a && a <= b'Z') as u8) << 5); + a_to_ascii_lower == b + }) +} + // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck // with this implementation ourselves until we want to make a breaking change. // (would have to drop it from `Num` though) @@ -212,12 +231,26 @@ macro_rules! float_trait_impl { use self::FloatErrorKind::*; use self::ParseFloatError as PFE; + // Special case radix 10 to use more accurate standard library implementation + if radix == 10 { + return src.parse().map_err(|_| PFE { + kind: if src.is_empty() { Empty } else { Invalid }, + }); + } + // Special values - match src { - "inf" => return Ok(core::$t::INFINITY), - "-inf" => return Ok(core::$t::NEG_INFINITY), - "NaN" => return Ok(core::$t::NAN), - _ => {}, + if str_to_ascii_lower_eq_str(src, "inf") + || str_to_ascii_lower_eq_str(src, "infinity") + { + return Ok(core::$t::INFINITY); + } else if str_to_ascii_lower_eq_str(src, "-inf") + || str_to_ascii_lower_eq_str(src, "-infinity") + { + return Ok(core::$t::NEG_INFINITY); + } else if str_to_ascii_lower_eq_str(src, "nan") { + return Ok(core::$t::NAN); + } else if str_to_ascii_lower_eq_str(src, "-nan") { + return Ok(-core::$t::NAN); } fn slice_shift_char(src: &str) -> Option<(char, &str)> { @@ -497,6 +530,28 @@ fn from_str_radix_multi_byte_fail() { } #[test] +fn from_str_radix_ignore_case() { + assert_eq!( + f32::from_str_radix("InF", 16).unwrap(), + ::core::f32::INFINITY + ); + assert_eq!( + f32::from_str_radix("InfinitY", 16).unwrap(), + ::core::f32::INFINITY + ); + assert_eq!( + f32::from_str_radix("-InF", 8).unwrap(), + ::core::f32::NEG_INFINITY + ); + assert_eq!( + f32::from_str_radix("-InfinitY", 8).unwrap(), + ::core::f32::NEG_INFINITY + ); + assert!(f32::from_str_radix("nAn", 4).unwrap().is_nan()); + assert!(f32::from_str_radix("-nAn", 4).unwrap().is_nan()); +} + +#[test] fn wrapping_is_num() { fn require_num<T: Num>(_: &T) {} require_num(&Wrapping(42_u32)); @@ -570,5 +625,16 @@ fn check_numassign_ops() { assert_eq!(compute(1, 2), 1) } -// TODO test `NumAssignRef`, but even the standard numeric types don't -// implement this yet. (see rust pr41336) +#[cfg(has_int_assignop_ref)] +#[test] +fn check_numassignref_ops() { + fn compute<T: NumAssignRef + Copy>(mut x: T, y: &T) -> T { + x *= y; + x /= y; + x %= y; + x += y; + x -= y; + x + } + assert_eq!(compute(1, &2), 1) +} diff --git a/vendor/num-traits/src/macros.rs b/vendor/num-traits/src/macros.rs index 4330cdfd8..b97758e42 100644 --- a/vendor/num-traits/src/macros.rs +++ b/vendor/num-traits/src/macros.rs @@ -23,7 +23,14 @@ macro_rules! forward { fn $method( $( $arg : $ty ),* ) -> $ret { <Self as $base>::$method( $( $arg ),* ) } - )*} + )*}; + ($( $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) + => {$( + #[inline] + fn $method(self $( , $arg : $ty )* ) -> $ret { + $imp(self $( , $arg )* ) + } + )*}; } macro_rules! constant { diff --git a/vendor/num-traits/src/ops/euclid.rs b/vendor/num-traits/src/ops/euclid.rs new file mode 100644 index 000000000..99b51279f --- /dev/null +++ b/vendor/num-traits/src/ops/euclid.rs @@ -0,0 +1,347 @@ +use core::ops::{Div, Rem}; + +pub trait Euclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> { + /// Calculates Euclidean division, the matching method for `rem_euclid`. + /// + /// This computes the integer `n` such that + /// `self = n * v + self.rem_euclid(v)`. + /// In other words, the result is `self / v` rounded to the integer `n` + /// such that `self >= n * v`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::Euclid; + /// + /// let a: i32 = 7; + /// let b: i32 = 4; + /// assert_eq!(Euclid::div_euclid(&a, &b), 1); // 7 > 4 * 1 + /// assert_eq!(Euclid::div_euclid(&-a, &b), -2); // -7 >= 4 * -2 + /// assert_eq!(Euclid::div_euclid(&a, &-b), -1); // 7 >= -4 * -1 + /// assert_eq!(Euclid::div_euclid(&-a, &-b), 2); // -7 >= -4 * 2 + /// ``` + fn div_euclid(&self, v: &Self) -> Self; + + /// Calculates the least nonnegative remainder of `self (mod v)`. + /// + /// In particular, the return value `r` satisfies `0.0 <= r < v.abs()` in + /// most cases. However, due to a floating point round-off error it can + /// result in `r == v.abs()`, violating the mathematical definition, if + /// `self` is much smaller than `v.abs()` in magnitude and `self < 0.0`. + /// This result is not an element of the function's codomain, but it is the + /// closest floating point number in the real numbers and thus fulfills the + /// property `self == self.div_euclid(v) * v + self.rem_euclid(v)` + /// approximatively. + /// + /// # Examples + /// + /// ``` + /// use num_traits::Euclid; + /// + /// let a: i32 = 7; + /// let b: i32 = 4; + /// assert_eq!(Euclid::rem_euclid(&a, &b), 3); + /// assert_eq!(Euclid::rem_euclid(&-a, &b), 1); + /// assert_eq!(Euclid::rem_euclid(&a, &-b), 3); + /// assert_eq!(Euclid::rem_euclid(&-a, &-b), 1); + /// ``` + fn rem_euclid(&self, v: &Self) -> Self; +} + +macro_rules! euclid_forward_impl { + ($($t:ty)*) => {$( + #[cfg(has_div_euclid)] + impl Euclid for $t { + #[inline] + fn div_euclid(&self, v: &$t) -> Self { + <$t>::div_euclid(*self, *v) + } + + #[inline] + fn rem_euclid(&self, v: &$t) -> Self { + <$t>::rem_euclid(*self, *v) + } + } + )*} +} + +macro_rules! euclid_int_impl { + ($($t:ty)*) => {$( + euclid_forward_impl!($t); + + #[cfg(not(has_div_euclid))] + impl Euclid for $t { + #[inline] + fn div_euclid(&self, v: &$t) -> Self { + let q = self / v; + if self % v < 0 { + return if *v > 0 { q - 1 } else { q + 1 } + } + q + } + + #[inline] + fn rem_euclid(&self, v: &$t) -> Self { + let r = self % v; + if r < 0 { + if *v < 0 { + r - v + } else { + r + v + } + } else { + r + } + } + } + )*} +} + +macro_rules! euclid_uint_impl { + ($($t:ty)*) => {$( + euclid_forward_impl!($t); + + #[cfg(not(has_div_euclid))] + impl Euclid for $t { + #[inline] + fn div_euclid(&self, v: &$t) -> Self { + self / v + } + + #[inline] + fn rem_euclid(&self, v: &$t) -> Self { + self % v + } + } + )*} +} + +euclid_int_impl!(isize i8 i16 i32 i64); +euclid_uint_impl!(usize u8 u16 u32 u64); +#[cfg(has_i128)] +euclid_int_impl!(i128); +#[cfg(has_i128)] +euclid_uint_impl!(u128); + +#[cfg(all(has_div_euclid, feature = "std"))] +euclid_forward_impl!(f32 f64); + +#[cfg(not(all(has_div_euclid, feature = "std")))] +impl Euclid for f32 { + #[inline] + fn div_euclid(&self, v: &f32) -> f32 { + let q = <f32 as ::float::FloatCore>::trunc(self / v); + if self % v < 0.0 { + return if *v > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn rem_euclid(&self, v: &f32) -> f32 { + let r = self % v; + if r < 0.0 { + r + <f32 as ::float::FloatCore>::abs(*v) + } else { + r + } + } +} + +#[cfg(not(all(has_div_euclid, feature = "std")))] +impl Euclid for f64 { + #[inline] + fn div_euclid(&self, v: &f64) -> f64 { + let q = <f64 as ::float::FloatCore>::trunc(self / v); + if self % v < 0.0 { + return if *v > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn rem_euclid(&self, v: &f64) -> f64 { + let r = self % v; + if r < 0.0 { + r + <f64 as ::float::FloatCore>::abs(*v) + } else { + r + } + } +} + +pub trait CheckedEuclid: Euclid { + /// Performs euclid division that returns `None` instead of panicking on division by zero + /// and instead of wrapping around on underflow and overflow. + fn checked_div_euclid(&self, v: &Self) -> Option<Self>; + + /// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and + /// division by zero. If any of that happens, `None` is returned. + fn checked_rem_euclid(&self, v: &Self) -> Option<Self>; +} + +macro_rules! checked_euclid_forward_impl { + ($($t:ty)*) => {$( + #[cfg(has_div_euclid)] + impl CheckedEuclid for $t { + #[inline] + fn checked_div_euclid(&self, v: &$t) -> Option<Self> { + <$t>::checked_div_euclid(*self, *v) + } + + #[inline] + fn checked_rem_euclid(&self, v: &$t) -> Option<Self> { + <$t>::checked_rem_euclid(*self, *v) + } + } + )*} +} + +macro_rules! checked_euclid_int_impl { + ($($t:ty)*) => {$( + checked_euclid_forward_impl!($t); + + #[cfg(not(has_div_euclid))] + impl CheckedEuclid for $t { + #[inline] + fn checked_div_euclid(&self, v: &$t) -> Option<$t> { + if *v == 0 || (*self == Self::min_value() && *v == -1) { + None + } else { + Some(Euclid::div_euclid(self, v)) + } + } + + #[inline] + fn checked_rem_euclid(&self, v: &$t) -> Option<$t> { + if *v == 0 || (*self == Self::min_value() && *v == -1) { + None + } else { + Some(Euclid::rem_euclid(self, v)) + } + } + } + )*} +} + +macro_rules! checked_euclid_uint_impl { + ($($t:ty)*) => {$( + checked_euclid_forward_impl!($t); + + #[cfg(not(has_div_euclid))] + impl CheckedEuclid for $t { + #[inline] + fn checked_div_euclid(&self, v: &$t) -> Option<$t> { + if *v == 0 { + None + } else { + Some(Euclid::div_euclid(self, v)) + } + } + + #[inline] + fn checked_rem_euclid(&self, v: &$t) -> Option<$t> { + if *v == 0 { + None + } else { + Some(Euclid::rem_euclid(self, v)) + } + } + } + )*} +} + +checked_euclid_int_impl!(isize i8 i16 i32 i64); +checked_euclid_uint_impl!(usize u8 u16 u32 u64); +#[cfg(has_i128)] +checked_euclid_int_impl!(i128); +#[cfg(has_i128)] +checked_euclid_uint_impl!(u128); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn euclid_unsigned() { + macro_rules! test_euclid { + ($($t:ident)+) => { + $( + { + let x: $t = 10; + let y: $t = 3; + assert_eq!(Euclid::div_euclid(&x, &y), 3); + assert_eq!(Euclid::rem_euclid(&x, &y), 1); + } + )+ + }; + } + + test_euclid!(usize u8 u16 u32 u64); + } + + #[test] + fn euclid_signed() { + macro_rules! test_euclid { + ($($t:ident)+) => { + $( + { + let x: $t = 10; + let y: $t = -3; + assert_eq!(Euclid::div_euclid(&x, &y), -3); + assert_eq!(Euclid::div_euclid(&-x, &y), 4); + assert_eq!(Euclid::rem_euclid(&x, &y), 1); + assert_eq!(Euclid::rem_euclid(&-x, &y), 2); + let x: $t = $t::min_value() + 1; + let y: $t = -1; + assert_eq!(Euclid::div_euclid(&x, &y), $t::max_value()); + } + )+ + }; + } + + test_euclid!(isize i8 i16 i32 i64); + } + + #[test] + fn euclid_float() { + macro_rules! test_euclid { + ($($t:ident)+) => { + $( + { + let x: $t = 12.1; + let y: $t = 3.2; + assert!(Euclid::div_euclid(&x, &y) * y + Euclid::rem_euclid(&x, &y) - x + <= 46.4 * <$t as ::float::FloatCore>::epsilon()); + assert!(Euclid::div_euclid(&x, &-y) * -y + Euclid::rem_euclid(&x, &-y) - x + <= 46.4 * <$t as ::float::FloatCore>::epsilon()); + assert!(Euclid::div_euclid(&-x, &y) * y + Euclid::rem_euclid(&-x, &y) + x + <= 46.4 * <$t as ::float::FloatCore>::epsilon()); + assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x + <= 46.4 * <$t as ::float::FloatCore>::epsilon()); + } + )+ + }; + } + + test_euclid!(f32 f64); + } + + #[test] + fn euclid_checked() { + macro_rules! test_euclid_checked { + ($($t:ident)+) => { + $( + { + assert_eq!(CheckedEuclid::checked_div_euclid(&$t::min_value(), &-1), None); + assert_eq!(CheckedEuclid::checked_rem_euclid(&$t::min_value(), &-1), None); + assert_eq!(CheckedEuclid::checked_div_euclid(&1, &0), None); + assert_eq!(CheckedEuclid::checked_rem_euclid(&1, &0), None); + } + )+ + }; + } + + test_euclid_checked!(isize i8 i16 i32 i64); + } +} diff --git a/vendor/num-traits/src/ops/mod.rs b/vendor/num-traits/src/ops/mod.rs index fd1695d99..585879f6f 100644 --- a/vendor/num-traits/src/ops/mod.rs +++ b/vendor/num-traits/src/ops/mod.rs @@ -1,5 +1,7 @@ pub mod checked; +pub mod euclid; pub mod inv; pub mod mul_add; +pub mod overflowing; pub mod saturating; pub mod wrapping; diff --git a/vendor/num-traits/src/ops/overflowing.rs b/vendor/num-traits/src/ops/overflowing.rs new file mode 100644 index 000000000..56118a032 --- /dev/null +++ b/vendor/num-traits/src/ops/overflowing.rs @@ -0,0 +1,104 @@ +use core::ops::{Add, Mul, Sub}; +#[cfg(has_i128)] +use core::{i128, u128}; +use core::{i16, i32, i64, i8, isize}; +use core::{u16, u32, u64, u8, usize}; + +macro_rules! overflowing_impl { + ($trait_name:ident, $method:ident, $t:ty) => { + impl $trait_name for $t { + #[inline] + fn $method(&self, v: &Self) -> (Self, bool) { + <$t>::$method(*self, *v) + } + } + }; +} + +/// Performs addition with a flag for overflow. +pub trait OverflowingAdd: Sized + Add<Self, Output = Self> { + /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow would occur. + /// If an overflow would have occurred then the wrapped value is returned. + fn overflowing_add(&self, v: &Self) -> (Self, bool); +} + +overflowing_impl!(OverflowingAdd, overflowing_add, u8); +overflowing_impl!(OverflowingAdd, overflowing_add, u16); +overflowing_impl!(OverflowingAdd, overflowing_add, u32); +overflowing_impl!(OverflowingAdd, overflowing_add, u64); +overflowing_impl!(OverflowingAdd, overflowing_add, usize); +#[cfg(has_i128)] +overflowing_impl!(OverflowingAdd, overflowing_add, u128); + +overflowing_impl!(OverflowingAdd, overflowing_add, i8); +overflowing_impl!(OverflowingAdd, overflowing_add, i16); +overflowing_impl!(OverflowingAdd, overflowing_add, i32); +overflowing_impl!(OverflowingAdd, overflowing_add, i64); +overflowing_impl!(OverflowingAdd, overflowing_add, isize); +#[cfg(has_i128)] +overflowing_impl!(OverflowingAdd, overflowing_add, i128); + +/// Performs substraction with a flag for overflow. +pub trait OverflowingSub: Sized + Sub<Self, Output = Self> { + /// Returns a tuple of the difference along with a boolean indicating whether an arithmetic overflow would occur. + /// If an overflow would have occurred then the wrapped value is returned. + fn overflowing_sub(&self, v: &Self) -> (Self, bool); +} + +overflowing_impl!(OverflowingSub, overflowing_sub, u8); +overflowing_impl!(OverflowingSub, overflowing_sub, u16); +overflowing_impl!(OverflowingSub, overflowing_sub, u32); +overflowing_impl!(OverflowingSub, overflowing_sub, u64); +overflowing_impl!(OverflowingSub, overflowing_sub, usize); +#[cfg(has_i128)] +overflowing_impl!(OverflowingSub, overflowing_sub, u128); + +overflowing_impl!(OverflowingSub, overflowing_sub, i8); +overflowing_impl!(OverflowingSub, overflowing_sub, i16); +overflowing_impl!(OverflowingSub, overflowing_sub, i32); +overflowing_impl!(OverflowingSub, overflowing_sub, i64); +overflowing_impl!(OverflowingSub, overflowing_sub, isize); +#[cfg(has_i128)] +overflowing_impl!(OverflowingSub, overflowing_sub, i128); + +/// Performs multiplication with a flag for overflow. +pub trait OverflowingMul: Sized + Mul<Self, Output = Self> { + /// Returns a tuple of the product along with a boolean indicating whether an arithmetic overflow would occur. + /// If an overflow would have occurred then the wrapped value is returned. + fn overflowing_mul(&self, v: &Self) -> (Self, bool); +} + +overflowing_impl!(OverflowingMul, overflowing_mul, u8); +overflowing_impl!(OverflowingMul, overflowing_mul, u16); +overflowing_impl!(OverflowingMul, overflowing_mul, u32); +overflowing_impl!(OverflowingMul, overflowing_mul, u64); +overflowing_impl!(OverflowingMul, overflowing_mul, usize); +#[cfg(has_i128)] +overflowing_impl!(OverflowingMul, overflowing_mul, u128); + +overflowing_impl!(OverflowingMul, overflowing_mul, i8); +overflowing_impl!(OverflowingMul, overflowing_mul, i16); +overflowing_impl!(OverflowingMul, overflowing_mul, i32); +overflowing_impl!(OverflowingMul, overflowing_mul, i64); +overflowing_impl!(OverflowingMul, overflowing_mul, isize); +#[cfg(has_i128)] +overflowing_impl!(OverflowingMul, overflowing_mul, i128); + +#[test] +fn test_overflowing_traits() { + fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) { + a.overflowing_add(&b) + } + fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) { + a.overflowing_sub(&b) + } + fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) { + a.overflowing_mul(&b) + } + assert_eq!(overflowing_add(5i16, 2), (7, false)); + assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true)); + assert_eq!(overflowing_sub(5i16, 2), (3, false)); + assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true)); + assert_eq!(overflowing_mul(5i16, 2), (10, false)); + assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true)); +} diff --git a/vendor/num-traits/src/sign.rs b/vendor/num-traits/src/sign.rs index 26d44c500..5c32071c2 100644 --- a/vendor/num-traits/src/sign.rs +++ b/vendor/num-traits/src/sign.rs @@ -213,13 +213,12 @@ fn unsigned_wrapping_is_unsigned() { fn require_unsigned<T: Unsigned>(_: &T) {} require_unsigned(&Wrapping(42_u32)); } -/* + // Commenting this out since it doesn't compile on Rust 1.8, // because on this version Wrapping doesn't implement Neg and therefore can't // implement Signed. -#[test] -fn signed_wrapping_is_signed() { - fn require_signed<T: Signed>(_: &T) {} - require_signed(&Wrapping(-42)); -} -*/ +// #[test] +// fn signed_wrapping_is_signed() { +// fn require_signed<T: Signed>(_: &T) {} +// require_signed(&Wrapping(-42)); +// } |