Add CheckedRem and CheckedNeg
This commit is contained in:
parent
bb67a3d03a
commit
138abc7b58
|
@ -1,5 +1,5 @@
|
|||
use core::{usize, u8, u16, u32, u64};
|
||||
use core::{isize, i8, i16, i32, i64};
|
||||
use core::{usize, u16, u32, u64, u8};
|
||||
use core::{isize, i16, i32, i64, i8};
|
||||
use core::{f32, f64};
|
||||
use core::num::Wrapping;
|
||||
|
||||
|
@ -25,20 +25,24 @@ macro_rules! bounded_impl {
|
|||
}
|
||||
|
||||
bounded_impl!(usize, usize::MIN, usize::MAX);
|
||||
bounded_impl!(u8, u8::MIN, u8::MAX);
|
||||
bounded_impl!(u16, u16::MIN, u16::MAX);
|
||||
bounded_impl!(u32, u32::MIN, u32::MAX);
|
||||
bounded_impl!(u64, u64::MIN, u64::MAX);
|
||||
bounded_impl!(u8, u8::MIN, u8::MAX);
|
||||
bounded_impl!(u16, u16::MIN, u16::MAX);
|
||||
bounded_impl!(u32, u32::MIN, u32::MAX);
|
||||
bounded_impl!(u64, u64::MIN, u64::MAX);
|
||||
|
||||
bounded_impl!(isize, isize::MIN, isize::MAX);
|
||||
bounded_impl!(i8, i8::MIN, i8::MAX);
|
||||
bounded_impl!(i16, i16::MIN, i16::MAX);
|
||||
bounded_impl!(i32, i32::MIN, i32::MAX);
|
||||
bounded_impl!(i64, i64::MIN, i64::MAX);
|
||||
bounded_impl!(i8, i8::MIN, i8::MAX);
|
||||
bounded_impl!(i16, i16::MIN, i16::MAX);
|
||||
bounded_impl!(i32, i32::MIN, i32::MAX);
|
||||
bounded_impl!(i64, i64::MIN, i64::MAX);
|
||||
|
||||
impl<T: Bounded> Bounded for Wrapping<T> {
|
||||
fn min_value() -> Self { Wrapping(T::min_value()) }
|
||||
fn max_value() -> Self { Wrapping(T::max_value()) }
|
||||
fn min_value() -> Self {
|
||||
Wrapping(T::min_value())
|
||||
}
|
||||
fn max_value() -> Self {
|
||||
Wrapping(T::max_value())
|
||||
}
|
||||
}
|
||||
|
||||
bounded_impl!(f32, f32::MIN, f32::MAX);
|
||||
|
@ -76,7 +80,6 @@ macro_rules! bounded_tuple {
|
|||
for_each_tuple!(bounded_tuple);
|
||||
bounded_impl!(f64, f64::MIN, f64::MAX);
|
||||
|
||||
|
||||
#[test]
|
||||
fn wrapping_bounded() {
|
||||
macro_rules! test_wrapping_bounded {
|
||||
|
|
76
src/cast.rs
76
src/cast.rs
|
@ -1,5 +1,5 @@
|
|||
use core::{i8, i16, i32, i64, isize};
|
||||
use core::{u8, u16, u32, u64, usize};
|
||||
use core::{isize, i16, i32, i64, i8};
|
||||
use core::{usize, u16, u32, u64, u8};
|
||||
use core::{f32, f64};
|
||||
use core::mem::size_of;
|
||||
use core::num::Wrapping;
|
||||
|
@ -402,29 +402,35 @@ macro_rules! impl_from_primitive {
|
|||
}
|
||||
|
||||
impl_from_primitive!(isize, to_isize);
|
||||
impl_from_primitive!(i8, to_i8);
|
||||
impl_from_primitive!(i16, to_i16);
|
||||
impl_from_primitive!(i32, to_i32);
|
||||
impl_from_primitive!(i64, to_i64);
|
||||
impl_from_primitive!(i8, to_i8);
|
||||
impl_from_primitive!(i16, to_i16);
|
||||
impl_from_primitive!(i32, to_i32);
|
||||
impl_from_primitive!(i64, to_i64);
|
||||
impl_from_primitive!(usize, to_usize);
|
||||
impl_from_primitive!(u8, to_u8);
|
||||
impl_from_primitive!(u16, to_u16);
|
||||
impl_from_primitive!(u32, to_u32);
|
||||
impl_from_primitive!(u64, to_u64);
|
||||
impl_from_primitive!(f32, to_f32);
|
||||
impl_from_primitive!(f64, to_f64);
|
||||
|
||||
impl_from_primitive!(u8, to_u8);
|
||||
impl_from_primitive!(u16, to_u16);
|
||||
impl_from_primitive!(u32, to_u32);
|
||||
impl_from_primitive!(u64, to_u64);
|
||||
impl_from_primitive!(f32, to_f32);
|
||||
impl_from_primitive!(f64, to_f64);
|
||||
|
||||
impl<T: ToPrimitive> ToPrimitive for Wrapping<T> {
|
||||
fn to_i64(&self) -> Option<i64> { self.0.to_i64() }
|
||||
fn to_u64(&self) -> Option<u64> { self.0.to_u64() }
|
||||
fn to_i64(&self) -> Option<i64> {
|
||||
self.0.to_i64()
|
||||
}
|
||||
fn to_u64(&self) -> Option<u64> {
|
||||
self.0.to_u64()
|
||||
}
|
||||
}
|
||||
impl<T: FromPrimitive> FromPrimitive for Wrapping<T> {
|
||||
fn from_u64(n: u64) -> Option<Self> { T::from_u64(n).map(Wrapping) }
|
||||
fn from_i64(n: i64) -> Option<Self> { T::from_i64(n).map(Wrapping) }
|
||||
fn from_u64(n: u64) -> Option<Self> {
|
||||
T::from_u64(n).map(Wrapping)
|
||||
}
|
||||
fn from_i64(n: i64) -> Option<Self> {
|
||||
T::from_i64(n).map(Wrapping)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Cast from one machine scalar to another.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -461,18 +467,18 @@ macro_rules! impl_num_cast {
|
|||
)
|
||||
}
|
||||
|
||||
impl_num_cast!(u8, to_u8);
|
||||
impl_num_cast!(u16, to_u16);
|
||||
impl_num_cast!(u32, to_u32);
|
||||
impl_num_cast!(u64, to_u64);
|
||||
impl_num_cast!(u8, to_u8);
|
||||
impl_num_cast!(u16, to_u16);
|
||||
impl_num_cast!(u32, to_u32);
|
||||
impl_num_cast!(u64, to_u64);
|
||||
impl_num_cast!(usize, to_usize);
|
||||
impl_num_cast!(i8, to_i8);
|
||||
impl_num_cast!(i16, to_i16);
|
||||
impl_num_cast!(i32, to_i32);
|
||||
impl_num_cast!(i64, to_i64);
|
||||
impl_num_cast!(i8, to_i8);
|
||||
impl_num_cast!(i16, to_i16);
|
||||
impl_num_cast!(i32, to_i32);
|
||||
impl_num_cast!(i64, to_i64);
|
||||
impl_num_cast!(isize, to_isize);
|
||||
impl_num_cast!(f32, to_f32);
|
||||
impl_num_cast!(f64, to_f64);
|
||||
impl_num_cast!(f32, to_f32);
|
||||
impl_num_cast!(f64, to_f64);
|
||||
|
||||
impl<T: NumCast> NumCast for Wrapping<T> {
|
||||
fn from<U: ToPrimitive>(n: U) -> Option<Self> {
|
||||
|
@ -493,20 +499,20 @@ impl<T: NumCast> NumCast for Wrapping<T> {
|
|||
/// let three: i32 = (3.14159265f32).as_();
|
||||
/// assert_eq!(three, 3);
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// # 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));
|
||||
///
|
||||
///
|
||||
/// ```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)).
|
||||
///
|
||||
|
@ -514,10 +520,10 @@ impl<T: NumCast> NumCast for Wrapping<T> {
|
|||
/// # use num_traits::AsPrimitive;
|
||||
/// let x: f32 = (1e300f64).as_(); // UB
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
pub trait AsPrimitive<T>: 'static + Copy
|
||||
where
|
||||
T: 'static + Copy
|
||||
T: 'static + Copy,
|
||||
{
|
||||
/// Convert a value to another, using the `as` operator.
|
||||
fn as_(self) -> T;
|
||||
|
|
33
src/float.rs
33
src/float.rs
|
@ -586,7 +586,11 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
|
|||
if other.is_nan() {
|
||||
return self;
|
||||
}
|
||||
if self < other { self } else { other }
|
||||
if self < other {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the maximum of the two numbers.
|
||||
|
@ -616,7 +620,11 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
|
|||
if other.is_nan() {
|
||||
return self;
|
||||
}
|
||||
if self > other { self } else { other }
|
||||
if self > other {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the reciprocal (multiplicative inverse) of the number.
|
||||
|
@ -882,13 +890,7 @@ impl FloatCore for f64 {
|
|||
///
|
||||
/// This trait is only available with the `std` feature.
|
||||
#[cfg(feature = "std")]
|
||||
pub trait Float
|
||||
: Num
|
||||
+ Copy
|
||||
+ NumCast
|
||||
+ PartialOrd
|
||||
+ Neg<Output = Self>
|
||||
{
|
||||
pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
|
||||
/// Returns the `NaN` value.
|
||||
///
|
||||
/// ```
|
||||
|
@ -1770,7 +1772,6 @@ pub trait Float
|
|||
/// ```
|
||||
fn atanh(self) -> Self;
|
||||
|
||||
|
||||
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
|
||||
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
|
||||
///
|
||||
|
@ -1874,11 +1875,7 @@ macro_rules! float_impl {
|
|||
|
||||
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||
let bits: u32 = unsafe { mem::transmute(f) };
|
||||
let sign: i8 = if bits >> 31 == 0 {
|
||||
1
|
||||
} else {
|
||||
-1
|
||||
};
|
||||
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
|
||||
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
|
||||
let mantissa = if exponent == 0 {
|
||||
(bits & 0x7fffff) << 1
|
||||
|
@ -1892,11 +1889,7 @@ fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
|||
|
||||
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||
let bits: u64 = unsafe { mem::transmute(f) };
|
||||
let sign: i8 = if bits >> 63 == 0 {
|
||||
1
|
||||
} else {
|
||||
-1
|
||||
};
|
||||
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
|
||||
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
|
||||
let mantissa = if exponent == 0 {
|
||||
(bits & 0xfffffffffffff) << 1
|
||||
|
|
|
@ -37,21 +37,24 @@ macro_rules! zero_impl {
|
|||
}
|
||||
|
||||
zero_impl!(usize, 0usize);
|
||||
zero_impl!(u8, 0u8);
|
||||
zero_impl!(u16, 0u16);
|
||||
zero_impl!(u32, 0u32);
|
||||
zero_impl!(u64, 0u64);
|
||||
zero_impl!(u8, 0u8);
|
||||
zero_impl!(u16, 0u16);
|
||||
zero_impl!(u32, 0u32);
|
||||
zero_impl!(u64, 0u64);
|
||||
|
||||
zero_impl!(isize, 0isize);
|
||||
zero_impl!(i8, 0i8);
|
||||
zero_impl!(i16, 0i16);
|
||||
zero_impl!(i32, 0i32);
|
||||
zero_impl!(i64, 0i64);
|
||||
zero_impl!(i8, 0i8);
|
||||
zero_impl!(i16, 0i16);
|
||||
zero_impl!(i32, 0i32);
|
||||
zero_impl!(i64, 0i64);
|
||||
|
||||
zero_impl!(f32, 0.0f32);
|
||||
zero_impl!(f64, 0.0f64);
|
||||
|
||||
impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output=Wrapping<T>> {
|
||||
impl<T: Zero> Zero for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Add<Output = Wrapping<T>>,
|
||||
{
|
||||
fn is_zero(&self) -> bool {
|
||||
self.0.is_zero()
|
||||
}
|
||||
|
@ -60,7 +63,6 @@ impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output=Wrapping<T>> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Defines a multiplicative identity element for `Self`.
|
||||
pub trait One: Sized + Mul<Self, Output = Self> {
|
||||
/// Returns the multiplicative identity element of `Self`, `1`.
|
||||
|
@ -86,7 +88,10 @@ pub trait One: Sized + Mul<Self, Output = Self> {
|
|||
/// After a semver bump, this method will be required, and the
|
||||
/// `where Self: PartialEq` bound will be removed.
|
||||
#[inline]
|
||||
fn is_one(&self) -> bool where Self: PartialEq {
|
||||
fn is_one(&self) -> bool
|
||||
where
|
||||
Self: PartialEq,
|
||||
{
|
||||
*self == Self::one()
|
||||
}
|
||||
}
|
||||
|
@ -101,21 +106,24 @@ macro_rules! one_impl {
|
|||
}
|
||||
|
||||
one_impl!(usize, 1usize);
|
||||
one_impl!(u8, 1u8);
|
||||
one_impl!(u16, 1u16);
|
||||
one_impl!(u32, 1u32);
|
||||
one_impl!(u64, 1u64);
|
||||
one_impl!(u8, 1u8);
|
||||
one_impl!(u16, 1u16);
|
||||
one_impl!(u32, 1u32);
|
||||
one_impl!(u64, 1u64);
|
||||
|
||||
one_impl!(isize, 1isize);
|
||||
one_impl!(i8, 1i8);
|
||||
one_impl!(i16, 1i16);
|
||||
one_impl!(i32, 1i32);
|
||||
one_impl!(i64, 1i64);
|
||||
one_impl!(i8, 1i8);
|
||||
one_impl!(i16, 1i16);
|
||||
one_impl!(i32, 1i32);
|
||||
one_impl!(i64, 1i64);
|
||||
|
||||
one_impl!(f32, 1.0f32);
|
||||
one_impl!(f64, 1.0f64);
|
||||
|
||||
impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
|
||||
impl<T: One> One for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Mul<Output = Wrapping<T>>,
|
||||
{
|
||||
fn one() -> Self {
|
||||
Wrapping(T::one())
|
||||
}
|
||||
|
@ -124,11 +132,16 @@ impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
|
|||
// Some helper functions provided for backwards compatibility.
|
||||
|
||||
/// Returns the additive identity, `0`.
|
||||
#[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
|
||||
#[inline(always)]
|
||||
pub fn zero<T: Zero>() -> T {
|
||||
Zero::zero()
|
||||
}
|
||||
|
||||
/// Returns the multiplicative identity, `1`.
|
||||
#[inline(always)] pub fn one<T: One>() -> T { One::one() }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn one<T: One>() -> T {
|
||||
One::one()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrapping_identities() {
|
||||
|
|
48
src/int.rs
48
src/int.rs
|
@ -1,4 +1,4 @@
|
|||
use core::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
||||
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
|
||||
|
||||
use {Num, NumCast};
|
||||
use bounds::Bounded;
|
||||
|
@ -8,21 +8,23 @@ use ops::saturating::Saturating;
|
|||
pub trait PrimInt
|
||||
: Sized
|
||||
+ Copy
|
||||
+ Num + NumCast
|
||||
+ Num
|
||||
+ NumCast
|
||||
+ Bounded
|
||||
+ PartialOrd + Ord + Eq
|
||||
+ Not<Output=Self>
|
||||
+ BitAnd<Output=Self>
|
||||
+ BitOr<Output=Self>
|
||||
+ BitXor<Output=Self>
|
||||
+ Shl<usize, Output=Self>
|
||||
+ Shr<usize, Output=Self>
|
||||
+ CheckedAdd<Output=Self>
|
||||
+ CheckedSub<Output=Self>
|
||||
+ CheckedMul<Output=Self>
|
||||
+ CheckedDiv<Output=Self>
|
||||
+ Saturating
|
||||
{
|
||||
+ PartialOrd
|
||||
+ Ord
|
||||
+ Eq
|
||||
+ Not<Output = Self>
|
||||
+ BitAnd<Output = Self>
|
||||
+ BitOr<Output = Self>
|
||||
+ BitXor<Output = Self>
|
||||
+ Shl<usize, Output = Self>
|
||||
+ Shr<usize, Output = Self>
|
||||
+ CheckedAdd<Output = Self>
|
||||
+ CheckedSub<Output = Self>
|
||||
+ CheckedMul<Output = Self>
|
||||
+ CheckedDiv<Output = Self>
|
||||
+ Saturating {
|
||||
/// Returns the number of ones in the binary representation of `self`.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -364,13 +366,13 @@ macro_rules! prim_int_impl {
|
|||
}
|
||||
|
||||
// prim_int_impl!(type, signed, unsigned);
|
||||
prim_int_impl!(u8, i8, u8);
|
||||
prim_int_impl!(u16, i16, u16);
|
||||
prim_int_impl!(u32, i32, u32);
|
||||
prim_int_impl!(u64, i64, u64);
|
||||
prim_int_impl!(u8, i8, u8);
|
||||
prim_int_impl!(u16, i16, u16);
|
||||
prim_int_impl!(u32, i32, u32);
|
||||
prim_int_impl!(u64, i64, u64);
|
||||
prim_int_impl!(usize, isize, usize);
|
||||
prim_int_impl!(i8, i8, u8);
|
||||
prim_int_impl!(i16, i16, u16);
|
||||
prim_int_impl!(i32, i32, u32);
|
||||
prim_int_impl!(i64, i64, u64);
|
||||
prim_int_impl!(i8, i8, u8);
|
||||
prim_int_impl!(i16, i16, u16);
|
||||
prim_int_impl!(i32, i32, u32);
|
||||
prim_int_impl!(i64, i64, u64);
|
||||
prim_int_impl!(isize, isize, usize);
|
||||
|
|
97
src/lib.rs
97
src/lib.rs
|
@ -15,15 +15,13 @@
|
|||
//! The `num-traits` crate is tested for rustc 1.8 and greater.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
|
||||
|
||||
#![deny(unconditional_recursion)]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
use core::ops::{Add, Sub, Mul, Div, Rem};
|
||||
use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
||||
use core::ops::{Add, Div, Mul, Rem, Sub};
|
||||
use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
|
||||
use core::num::Wrapping;
|
||||
use core::fmt;
|
||||
|
||||
|
@ -32,15 +30,15 @@ pub use bounds::Bounded;
|
|||
pub use float::Float;
|
||||
pub use float::FloatConst;
|
||||
// pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
||||
pub use identities::{Zero, One, zero, one};
|
||||
pub use identities::{one, zero, One, Zero};
|
||||
pub use ops::inv::Inv;
|
||||
pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr};
|
||||
pub use ops::checked::{CheckedAdd, CheckedDiv, CheckedMul, CheckedShl, CheckedShr, CheckedSub};
|
||||
pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub};
|
||||
pub use ops::saturating::Saturating;
|
||||
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
|
||||
pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast};
|
||||
pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
|
||||
pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
|
||||
pub use int::PrimInt;
|
||||
pub use pow::{Pow, pow, checked_pow};
|
||||
pub use pow::{checked_pow, pow, Pow};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
@ -58,8 +56,7 @@ pub mod pow;
|
|||
|
||||
/// The base trait for numeric types, covering `0` and `1` values,
|
||||
/// comparisons, basic numeric operations, and string conversion.
|
||||
pub trait Num: PartialEq + Zero + One + NumOps
|
||||
{
|
||||
pub trait Num: PartialEq + Zero + One + NumOps {
|
||||
type FromStrRadixErr;
|
||||
|
||||
/// Convert from a string and radix <= 36.
|
||||
|
@ -86,63 +83,75 @@ pub trait NumOps<Rhs = Self, Output = Self>
|
|||
+ Sub<Rhs, Output = Output>
|
||||
+ Mul<Rhs, Output = Output>
|
||||
+ Div<Rhs, Output = Output>
|
||||
+ Rem<Rhs, Output = Output>
|
||||
{}
|
||||
+ Rem<Rhs, Output = Output> {
|
||||
}
|
||||
|
||||
impl<T, Rhs, Output> NumOps<Rhs, Output> for T
|
||||
where T: Add<Rhs, Output = Output>
|
||||
+ Sub<Rhs, Output = Output>
|
||||
+ Mul<Rhs, Output = Output>
|
||||
+ Div<Rhs, Output = Output>
|
||||
+ Rem<Rhs, Output = Output>
|
||||
{}
|
||||
where
|
||||
T: Add<Rhs, Output = Output>
|
||||
+ Sub<Rhs, Output = Output>
|
||||
+ Mul<Rhs, Output = Output>
|
||||
+ Div<Rhs, Output = Output>
|
||||
+ Rem<Rhs, Output = Output>,
|
||||
{
|
||||
}
|
||||
|
||||
/// The trait for `Num` types which also implement numeric operations taking
|
||||
/// the second operand by reference.
|
||||
///
|
||||
/// This is automatically implemented for types which implement the operators.
|
||||
pub trait NumRef: Num + for<'r> NumOps<&'r Self> {}
|
||||
impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {}
|
||||
impl<T> NumRef for T
|
||||
where
|
||||
T: Num + for<'r> NumOps<&'r T>,
|
||||
{
|
||||
}
|
||||
|
||||
/// The trait for 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.
|
||||
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> {}
|
||||
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 `+=`).
|
||||
///
|
||||
/// This is automatically implemented for types which implement the operators.
|
||||
pub trait NumAssignOps<Rhs = Self>
|
||||
: AddAssign<Rhs>
|
||||
+ SubAssign<Rhs>
|
||||
+ MulAssign<Rhs>
|
||||
+ DivAssign<Rhs>
|
||||
+ RemAssign<Rhs>
|
||||
{}
|
||||
: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, Rhs> NumAssignOps<Rhs> for T
|
||||
where T: AddAssign<Rhs>
|
||||
+ SubAssign<Rhs>
|
||||
+ MulAssign<Rhs>
|
||||
+ DivAssign<Rhs>
|
||||
+ RemAssign<Rhs>
|
||||
{}
|
||||
where
|
||||
T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>,
|
||||
{
|
||||
}
|
||||
|
||||
/// The trait for `Num` types which also implement assignment operators.
|
||||
///
|
||||
/// This is automatically implemented for types which implement the operators.
|
||||
pub trait NumAssign: Num + NumAssignOps {}
|
||||
impl<T> NumAssign for T where T: Num + NumAssignOps {}
|
||||
impl<T> NumAssign for T
|
||||
where
|
||||
T: Num + NumAssignOps,
|
||||
{
|
||||
}
|
||||
|
||||
/// The trait for `NumAssign` types which also implement assignment operations
|
||||
/// taking the second operand by reference.
|
||||
///
|
||||
/// This is automatically implemented for types which implement the operators.
|
||||
pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
|
||||
impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
|
||||
|
||||
impl<T> NumAssignRef for T
|
||||
where
|
||||
T: NumAssign + for<'r> NumAssignOps<&'r T>,
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! int_trait_impl {
|
||||
($name:ident for $($t:ty)*) => ($(
|
||||
|
@ -160,9 +169,12 @@ macro_rules! int_trait_impl {
|
|||
int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
|
||||
|
||||
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>>
|
||||
where
|
||||
Wrapping<T>: Add<Output = Wrapping<T>>
|
||||
+ Sub<Output = Wrapping<T>>
|
||||
+ Mul<Output = Wrapping<T>>
|
||||
+ Div<Output = Wrapping<T>>
|
||||
+ Rem<Output = Wrapping<T>>,
|
||||
{
|
||||
type FromStrRadixErr = T::FromStrRadixErr;
|
||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||
|
@ -170,7 +182,6 @@ impl<T: Num> Num for Wrapping<T>
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FloatErrorKind {
|
||||
Empty,
|
||||
|
@ -438,7 +449,8 @@ fn check_numref_ops() {
|
|||
#[test]
|
||||
fn check_refnum_ops() {
|
||||
fn compute<T: Copy>(x: &T, y: T) -> T
|
||||
where for<'a> &'a T: RefNum<T>
|
||||
where
|
||||
for<'a> &'a T: RefNum<T>,
|
||||
{
|
||||
&(&(&(&(x * y) / y) % y) + y) - y
|
||||
}
|
||||
|
@ -448,7 +460,8 @@ fn check_refnum_ops() {
|
|||
#[test]
|
||||
fn check_refref_ops() {
|
||||
fn compute<T>(x: &T, y: &T) -> T
|
||||
where for<'a> &'a T: RefNum<T>
|
||||
where
|
||||
for<'a> &'a T: RefNum<T>,
|
||||
{
|
||||
&(&(&(&(x * y) / y) % y) + y) - y
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use core::ops::{Add, Sub, Mul, Div, Shl, Shr};
|
||||
use core::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
||||
|
||||
/// Performs addition that returns `None` instead of wrapping around on
|
||||
/// overflow.
|
||||
pub trait CheckedAdd: Sized + Add<Self, Output=Self> {
|
||||
pub trait CheckedAdd: Sized + Add<Self, Output = Self> {
|
||||
/// Adds two numbers, checking for overflow. If overflow happens, `None` is
|
||||
/// returned.
|
||||
fn checked_add(&self, v: &Self) -> Option<Self>;
|
||||
|
@ -32,7 +32,7 @@ checked_impl!(CheckedAdd, checked_add, i64);
|
|||
checked_impl!(CheckedAdd, checked_add, isize);
|
||||
|
||||
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
|
||||
pub trait CheckedSub: Sized + Sub<Self, Output=Self> {
|
||||
pub trait CheckedSub: Sized + Sub<Self, Output = Self> {
|
||||
/// Subtracts two numbers, checking for underflow. If underflow happens,
|
||||
/// `None` is returned.
|
||||
fn checked_sub(&self, v: &Self) -> Option<Self>;
|
||||
|
@ -52,7 +52,7 @@ checked_impl!(CheckedSub, checked_sub, isize);
|
|||
|
||||
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
|
||||
/// overflow.
|
||||
pub trait CheckedMul: Sized + Mul<Self, Output=Self> {
|
||||
pub trait CheckedMul: Sized + Mul<Self, Output = Self> {
|
||||
/// Multiplies two numbers, checking for underflow or overflow. If underflow
|
||||
/// or overflow happens, `None` is returned.
|
||||
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
||||
|
@ -72,7 +72,7 @@ checked_impl!(CheckedMul, checked_mul, isize);
|
|||
|
||||
/// Performs division that returns `None` instead of panicking on division by zero and instead of
|
||||
/// wrapping around on underflow and overflow.
|
||||
pub trait CheckedDiv: Sized + Div<Self, Output=Self> {
|
||||
pub trait CheckedDiv: Sized + Div<Self, Output = Self> {
|
||||
/// Divides two numbers, checking for underflow, overflow and division by
|
||||
/// zero. If any of that happens, `None` is returned.
|
||||
fn checked_div(&self, v: &Self) -> Option<Self>;
|
||||
|
@ -90,8 +90,47 @@ checked_impl!(CheckedDiv, checked_div, i32);
|
|||
checked_impl!(CheckedDiv, checked_div, i64);
|
||||
checked_impl!(CheckedDiv, checked_div, isize);
|
||||
|
||||
// CheckedRem
|
||||
pub trait CheckedRem: Sized + Rem<Self, Output = Self> {
|
||||
fn checked_rem(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
checked_impl!(CheckedRem, checked_rem, u8);
|
||||
checked_impl!(CheckedRem, checked_rem, u16);
|
||||
checked_impl!(CheckedRem, checked_rem, u32);
|
||||
checked_impl!(CheckedRem, checked_rem, u64);
|
||||
checked_impl!(CheckedRem, checked_rem, usize);
|
||||
|
||||
checked_impl!(CheckedRem, checked_rem, i8);
|
||||
checked_impl!(CheckedRem, checked_rem, i16);
|
||||
checked_impl!(CheckedRem, checked_rem, i32);
|
||||
checked_impl!(CheckedRem, checked_rem, i64);
|
||||
checked_impl!(CheckedRem, checked_rem, isize);
|
||||
|
||||
// CheckedNeg
|
||||
macro_rules! checked_impl_one_para {
|
||||
($trait_name:ident, $method:ident, $t:ty) => {
|
||||
impl $trait_name for $t {
|
||||
#[inline]
|
||||
fn $method(&self) -> Option<$t> {
|
||||
<$t>::$method(*self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CheckedNeg: Sized + Neg<Output = Self> {
|
||||
fn checked_neg(&self) -> Option<Self>;
|
||||
}
|
||||
|
||||
checked_impl_one_para!(CheckedNeg, checked_neg, i8);
|
||||
checked_impl_one_para!(CheckedNeg, checked_neg, i16);
|
||||
checked_impl_one_para!(CheckedNeg, checked_neg, i32);
|
||||
checked_impl_one_para!(CheckedNeg, checked_neg, i64);
|
||||
checked_impl_one_para!(CheckedNeg, checked_neg, isize);
|
||||
|
||||
/// Performs a left shift that returns `None` on overflow.
|
||||
pub trait CheckedShl: Sized + Shl<u32, Output=Self> {
|
||||
pub trait CheckedShl: Sized + Shl<u32, Output = Self> {
|
||||
/// Shifts a number to the left, checking for overflow. If overflow happens,
|
||||
/// `None` is returned.
|
||||
///
|
||||
|
@ -132,7 +171,7 @@ checked_shift_impl!(CheckedShl, checked_shl, i64);
|
|||
checked_shift_impl!(CheckedShl, checked_shl, isize);
|
||||
|
||||
/// Performs a right shift that returns `None` on overflow.
|
||||
pub trait CheckedShr: Sized + Shr<u32, Output=Self> {
|
||||
pub trait CheckedShr: Sized + Shr<u32, Output = Self> {
|
||||
/// Shifts a number to the left, checking for overflow. If overflow happens,
|
||||
/// `None` is returned.
|
||||
///
|
||||
|
|
|
@ -20,20 +20,28 @@ pub trait Inv {
|
|||
impl Inv for f32 {
|
||||
type Output = f32;
|
||||
#[inline]
|
||||
fn inv(self) -> f32 { 1.0 / self }
|
||||
fn inv(self) -> f32 {
|
||||
1.0 / self
|
||||
}
|
||||
}
|
||||
impl Inv for f64 {
|
||||
type Output = f64;
|
||||
#[inline]
|
||||
fn inv(self) -> f64 { 1.0 / self }
|
||||
fn inv(self) -> f64 {
|
||||
1.0 / self
|
||||
}
|
||||
}
|
||||
impl<'a> Inv for &'a f32 {
|
||||
type Output = f32;
|
||||
#[inline]
|
||||
fn inv(self) -> f32 { 1.0 / *self }
|
||||
fn inv(self) -> f32 {
|
||||
1.0 / *self
|
||||
}
|
||||
}
|
||||
impl<'a> Inv for &'a f64 {
|
||||
type Output = f64;
|
||||
#[inline]
|
||||
fn inv(self) -> f64 { 1.0 / *self }
|
||||
fn inv(self) -> f64 {
|
||||
1.0 / *self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use core::ops::{Add, Sub, Mul};
|
||||
use core::ops::{Add, Mul, Sub};
|
||||
use core::num::Wrapping;
|
||||
|
||||
macro_rules! wrapping_impl {
|
||||
|
@ -21,7 +21,7 @@ macro_rules! wrapping_impl {
|
|||
}
|
||||
|
||||
/// Performs addition that wraps around on overflow.
|
||||
pub trait WrappingAdd: Sized + Add<Self, Output=Self> {
|
||||
pub trait WrappingAdd: Sized + Add<Self, Output = Self> {
|
||||
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
|
||||
/// the type.
|
||||
fn wrapping_add(&self, v: &Self) -> Self;
|
||||
|
@ -40,7 +40,7 @@ wrapping_impl!(WrappingAdd, wrapping_add, i64);
|
|||
wrapping_impl!(WrappingAdd, wrapping_add, isize);
|
||||
|
||||
/// Performs subtraction that wraps around on overflow.
|
||||
pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
|
||||
pub trait WrappingSub: Sized + Sub<Self, Output = Self> {
|
||||
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
|
||||
/// of the type.
|
||||
fn wrapping_sub(&self, v: &Self) -> Self;
|
||||
|
@ -59,7 +59,7 @@ wrapping_impl!(WrappingSub, wrapping_sub, i64);
|
|||
wrapping_impl!(WrappingSub, wrapping_sub, isize);
|
||||
|
||||
/// Performs multiplication that wraps around on overflow.
|
||||
pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
|
||||
pub trait WrappingMul: Sized + Mul<Self, Output = Self> {
|
||||
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
|
||||
/// of the type.
|
||||
fn wrapping_mul(&self, v: &Self) -> Self;
|
||||
|
@ -78,28 +78,42 @@ wrapping_impl!(WrappingMul, wrapping_mul, i64);
|
|||
wrapping_impl!(WrappingMul, wrapping_mul, isize);
|
||||
|
||||
// Well this is a bit funny, but all the more appropriate.
|
||||
impl<T: WrappingAdd> WrappingAdd for Wrapping<T> where Wrapping<T>: Add<Output = Wrapping<T>> {
|
||||
impl<T: WrappingAdd> WrappingAdd for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Add<Output = Wrapping<T>>,
|
||||
{
|
||||
fn wrapping_add(&self, v: &Self) -> Self {
|
||||
Wrapping(self.0.wrapping_add(&v.0))
|
||||
}
|
||||
}
|
||||
impl<T: WrappingSub> WrappingSub for Wrapping<T> where Wrapping<T>: Sub<Output = Wrapping<T>> {
|
||||
impl<T: WrappingSub> WrappingSub for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Sub<Output = Wrapping<T>>,
|
||||
{
|
||||
fn wrapping_sub(&self, v: &Self) -> Self {
|
||||
Wrapping(self.0.wrapping_sub(&v.0))
|
||||
}
|
||||
}
|
||||
impl<T: WrappingMul> WrappingMul for Wrapping<T> where Wrapping<T>: Mul<Output = Wrapping<T>> {
|
||||
impl<T: WrappingMul> WrappingMul for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Mul<Output = Wrapping<T>>,
|
||||
{
|
||||
fn wrapping_mul(&self, v: &Self) -> Self {
|
||||
Wrapping(self.0.wrapping_mul(&v.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_wrapping_traits() {
|
||||
fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
|
||||
fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
|
||||
fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&b) }
|
||||
fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T {
|
||||
a.wrapping_add(&b)
|
||||
}
|
||||
fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T {
|
||||
a.wrapping_sub(&b)
|
||||
}
|
||||
fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T {
|
||||
a.wrapping_mul(&b)
|
||||
}
|
||||
assert_eq!(wrapping_add(255, 1), 0u8);
|
||||
assert_eq!(wrapping_sub(0, 1), 255u8);
|
||||
assert_eq!(wrapping_mul(255, 2), 254u8);
|
||||
|
|
18
src/pow.rs
18
src/pow.rs
|
@ -1,6 +1,6 @@
|
|||
use core::ops::Mul;
|
||||
use core::num::Wrapping;
|
||||
use {One, CheckedMul};
|
||||
use {CheckedMul, One};
|
||||
|
||||
/// Binary operator for raising a value to a power.
|
||||
pub trait Pow<RHS> {
|
||||
|
@ -160,13 +160,17 @@ mod float_impls {
|
|||
/// ```
|
||||
#[inline]
|
||||
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
|
||||
if exp == 0 { return T::one() }
|
||||
if exp == 0 {
|
||||
return T::one();
|
||||
}
|
||||
|
||||
while exp & 1 == 0 {
|
||||
base = base.clone() * base;
|
||||
exp >>= 1;
|
||||
}
|
||||
if exp == 1 { return base }
|
||||
if exp == 1 {
|
||||
return base;
|
||||
}
|
||||
|
||||
let mut acc = base.clone();
|
||||
while exp > 1 {
|
||||
|
@ -194,7 +198,9 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
|
|||
/// ```
|
||||
#[inline]
|
||||
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
|
||||
if exp == 0 { return Some(T::one()) }
|
||||
if exp == 0 {
|
||||
return Some(T::one());
|
||||
}
|
||||
|
||||
macro_rules! optry {
|
||||
( $ expr : expr ) => {
|
||||
|
@ -206,7 +212,9 @@ pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) ->
|
|||
base = optry!(base.checked_mul(&base));
|
||||
exp >>= 1;
|
||||
}
|
||||
if exp == 1 { return Some(base) }
|
||||
if exp == 1 {
|
||||
return Some(base);
|
||||
}
|
||||
|
||||
let mut acc = base.clone();
|
||||
while exp > 1 {
|
||||
|
|
12
src/real.rs
12
src/real.rs
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Neg;
|
||||
|
||||
use {Num, NumCast, Float};
|
||||
use {Float, Num, NumCast};
|
||||
|
||||
// NOTE: These doctests have the same issue as those in src/float.rs.
|
||||
// They're testing the inherent methods directly, and not those of `Real`.
|
||||
|
@ -12,13 +12,7 @@ use {Num, NumCast, Float};
|
|||
/// for a list of data types that could meaningfully implement this trait.
|
||||
///
|
||||
/// This trait is only available with the `std` feature.
|
||||
pub trait Real
|
||||
: Num
|
||||
+ Copy
|
||||
+ NumCast
|
||||
+ PartialOrd
|
||||
+ Neg<Output = Self>
|
||||
{
|
||||
pub trait Real: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
|
||||
/// Returns the smallest finite value that this type can represent.
|
||||
///
|
||||
/// ```
|
||||
|
@ -272,7 +266,7 @@ pub trait Real
|
|||
|
||||
/// Take the square root of a number.
|
||||
///
|
||||
/// Returns NaN if `self` is a negative floating-point number.
|
||||
/// Returns NaN if `self` is a negative floating-point number.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
|
23
src/sign.rs
23
src/sign.rs
|
@ -74,7 +74,9 @@ macro_rules! signed_impl {
|
|||
|
||||
signed_impl!(isize i8 i16 i32 i64);
|
||||
|
||||
impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
|
||||
impl<T: Signed> Signed for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
|
||||
{
|
||||
#[inline]
|
||||
fn abs(&self) -> Self {
|
||||
|
@ -92,10 +94,14 @@ impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapp
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn is_positive(&self) -> bool { self.0.is_positive() }
|
||||
fn is_positive(&self) -> bool {
|
||||
self.0.is_positive()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_negative(&self) -> bool { self.0.is_negative() }
|
||||
fn is_negative(&self) -> bool {
|
||||
self.0.is_negative()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! signed_float_impl {
|
||||
|
@ -171,7 +177,10 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
|
|||
/// * `0` if the number is zero
|
||||
/// * `1` if the number is positive
|
||||
/// * `-1` if the number is negative
|
||||
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
|
||||
#[inline(always)]
|
||||
pub fn signum<T: Signed>(value: T) -> T {
|
||||
value.signum()
|
||||
}
|
||||
|
||||
/// A trait for values which cannot be negative
|
||||
pub trait Unsigned: Num {}
|
||||
|
@ -184,7 +193,11 @@ macro_rules! empty_trait_impl {
|
|||
|
||||
empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
|
||||
|
||||
impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}
|
||||
impl<T: Unsigned> Unsigned for Wrapping<T>
|
||||
where
|
||||
Wrapping<T>: Num,
|
||||
{
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_wrapping_is_unsigned() {
|
||||
|
|
Loading…
Reference in New Issue