diff --git a/src/float.rs b/src/float.rs index 4124e92c..20f9710d 100644 --- a/src/float.rs +++ b/src/float.rs @@ -969,10 +969,10 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg { /// Returns `-0.0`. /// /// ``` - /// use num_traits::{Zero, Float}; + /// use num_traits::{Float, PartialZero}; /// /// let inf: f32 = Float::infinity(); - /// let zero: f32 = Zero::zero(); + /// let zero: f32 = f32::zero(); /// let neg_zero: f32 = Float::neg_zero(); /// /// assert_eq!(zero, neg_zero); diff --git a/src/identities.rs b/src/identities.rs index 0a198a1f..761ffade 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -4,16 +4,13 @@ use core::ops::{Add, Mul}; #[cfg(has_num_saturating)] use core::num::Saturating; -/// Defines an additive identity element for `Self`. -/// -/// # Laws +/// Defines a distinguished `0` value for `Self`. /// -/// ```text -/// a + 0 = a ∀ a ∈ Self -/// 0 + a = a ∀ a ∈ Self -/// ``` -pub trait Zero: Sized + Add { - /// Returns the additive identity element of `Self`, `0`. +/// This trait does not require [`Add`]. Types that also implement addition +/// with `0` as an identity should implement [`Zero`]. +pub trait PartialZero: Sized { + /// Returns the distinguished `0` value of `Self`. + /// /// # Purity /// /// This function should return the same result at all times regardless of @@ -22,15 +19,25 @@ pub trait Zero: Sized + Add { // This cannot be an associated constant, because of bignums. fn zero() -> Self; - /// Sets `self` to the additive identity element of `Self`, `0`. + /// Sets `self` to the distinguished `0` value of `Self`. fn set_zero(&mut self) { - *self = Zero::zero(); + *self = PartialZero::zero(); } - /// Returns `true` if `self` is equal to the additive identity. + /// Returns `true` if `self` is equal to the distinguished `0` value. fn is_zero(&self) -> bool; } +/// Defines an additive identity element for `Self`. +/// +/// # Laws +/// +/// ```text +/// a + 0 = a ∀ a ∈ Self +/// 0 + a = a ∀ a ∈ Self +/// ``` +pub trait Zero: PartialZero + Add {} + /// Defines an associated constant representing the additive identity element /// for `Self`. pub trait ConstZero: Zero { @@ -40,7 +47,7 @@ pub trait ConstZero: Zero { macro_rules! zero_impl { ($t:ty, $v:expr) => { - impl Zero for $t { + impl PartialZero for $t { #[inline] fn zero() -> $t { $v @@ -51,6 +58,8 @@ macro_rules! zero_impl { } } + impl Zero for $t {} + impl ConstZero for $t { const ZERO: Self = $v; } @@ -74,10 +83,7 @@ zero_impl!(i128, 0); zero_impl!(f32, 0.0); zero_impl!(f64, 0.0); -impl Zero for Wrapping -where - Wrapping: Add>, -{ +impl PartialZero for Wrapping { fn is_zero(&self) -> bool { self.0.is_zero() } @@ -91,6 +97,8 @@ where } } +impl Zero for Wrapping where Wrapping: Add> {} + impl ConstZero for Wrapping where Wrapping: Add>, @@ -99,10 +107,7 @@ where } #[cfg(has_num_saturating)] -impl Zero for Saturating -where - Saturating: Add>, -{ +impl PartialZero for Saturating { fn is_zero(&self) -> bool { self.0.is_zero() } @@ -116,6 +121,9 @@ where } } +#[cfg(has_num_saturating)] +impl Zero for Saturating where Saturating: Add> {} + #[cfg(has_num_saturating)] impl ConstZero for Saturating where @@ -124,16 +132,12 @@ where const ZERO: Self = Saturating(T::ZERO); } -/// Defines a multiplicative identity element for `Self`. -/// -/// # Laws +/// Defines a distinguished `1` value for `Self`. /// -/// ```text -/// a * 1 = a ∀ a ∈ Self -/// 1 * a = a ∀ a ∈ Self -/// ``` -pub trait One: Sized + Mul { - /// Returns the multiplicative identity element of `Self`, `1`. +/// This trait does not require [`Mul`]. Types that also implement +/// multiplication with `1` as an identity should implement [`One`]. +pub trait PartialOne: Sized { + /// Returns the distinguished `1` value of `Self`. /// /// # Purity /// @@ -143,12 +147,12 @@ pub trait One: Sized + Mul { // This cannot be an associated constant, because of bignums. fn one() -> Self; - /// Sets `self` to the multiplicative identity element of `Self`, `1`. + /// Sets `self` to the distinguished `1` value of `Self`. fn set_one(&mut self) { - *self = One::one(); + *self = PartialOne::one(); } - /// Returns `true` if `self` is equal to the multiplicative identity. + /// Returns `true` if `self` is equal to the distinguished `1` value. /// /// For performance reasons, it's best to implement this manually. /// After a semver bump, this method will be required, and the @@ -162,6 +166,16 @@ pub trait One: Sized + Mul { } } +/// Defines a multiplicative identity element for `Self`. +/// +/// # Laws +/// +/// ```text +/// a * 1 = a ∀ a ∈ Self +/// 1 * a = a ∀ a ∈ Self +/// ``` +pub trait One: PartialOne + Mul {} + /// Defines an associated constant representing the multiplicative identity /// element for `Self`. pub trait ConstOne: One { @@ -171,7 +185,7 @@ pub trait ConstOne: One { macro_rules! one_impl { ($t:ty, $v:expr) => { - impl One for $t { + impl PartialOne for $t { #[inline] fn one() -> $t { $v @@ -182,6 +196,8 @@ macro_rules! one_impl { } } + impl One for $t {} + impl ConstOne for $t { const ONE: Self = $v; } @@ -205,10 +221,7 @@ one_impl!(i128, 1); one_impl!(f32, 1.0); one_impl!(f64, 1.0); -impl One for Wrapping -where - Wrapping: Mul>, -{ +impl PartialOne for Wrapping { fn set_one(&mut self) { self.0.set_one(); } @@ -218,6 +231,8 @@ where } } +impl One for Wrapping where Wrapping: Mul> {} + impl ConstOne for Wrapping where Wrapping: Mul>, @@ -226,10 +241,7 @@ where } #[cfg(has_num_saturating)] -impl One for Saturating -where - Saturating: Mul>, -{ +impl PartialOne for Saturating { fn set_one(&mut self) { self.0.set_one(); } @@ -239,6 +251,9 @@ where } } +#[cfg(has_num_saturating)] +impl One for Saturating where Saturating: Mul> {} + #[cfg(has_num_saturating)] impl ConstOne for Saturating where @@ -251,14 +266,14 @@ where /// Returns the additive identity, `0`. #[inline(always)] -pub fn zero() -> T { - Zero::zero() +pub fn zero() -> T { + PartialZero::zero() } /// Returns the multiplicative identity, `1`. #[inline(always)] -pub fn one() -> T { - One::one() +pub fn one() -> T { + PartialOne::one() } #[test] diff --git a/src/lib.rs b/src/lib.rs index 43212c77..cbb12ab3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ pub use crate::float::Float; pub use crate::float::FloatConst; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use crate::cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive}; -pub use crate::identities::{one, zero, ConstOne, ConstZero, One, Zero}; +pub use crate::identities::{one, zero, ConstOne, ConstZero, One, PartialOne, PartialZero, Zero}; pub use crate::int::PrimInt; pub use crate::ops::bytes::{FromBytes, ToBytes}; pub use crate::ops::checked::{