Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,10 +969,10 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
/// 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();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// let zero: f32 = f32::zero();
/// let zero: f32 = PartialZero::zero();

/// let neg_zero: f32 = Float::neg_zero();
///
/// assert_eq!(zero, neg_zero);
Expand Down
107 changes: 61 additions & 46 deletions src/identities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, Output = Self> {
/// 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
Expand All @@ -22,15 +19,25 @@ pub trait Zero: Sized + Add<Self, Output = Self> {
// 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<Self, Output = Self> {}

/// Defines an associated constant representing the additive identity element
/// for `Self`.
pub trait ConstZero: Zero {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the same be done for ConstZero, ConstOne?

Expand All @@ -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
Expand All @@ -51,6 +58,8 @@ macro_rules! zero_impl {
}
}

impl Zero for $t {}

impl ConstZero for $t {
const ZERO: Self = $v;
}
Expand All @@ -74,10 +83,7 @@ zero_impl!(i128, 0);
zero_impl!(f32, 0.0);
zero_impl!(f64, 0.0);

impl<T: Zero> Zero for Wrapping<T>
where
Wrapping<T>: Add<Output = Wrapping<T>>,
{
impl<T: PartialZero> PartialZero for Wrapping<T> {
fn is_zero(&self) -> bool {
self.0.is_zero()
}
Expand All @@ -91,6 +97,8 @@ where
}
}

impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output = Wrapping<T>> {}

impl<T: ConstZero> ConstZero for Wrapping<T>
where
Wrapping<T>: Add<Output = Wrapping<T>>,
Expand All @@ -99,10 +107,7 @@ where
}

#[cfg(has_num_saturating)]
impl<T: Zero> Zero for Saturating<T>
where
Saturating<T>: Add<Output = Saturating<T>>,
{
impl<T: PartialZero> PartialZero for Saturating<T> {
fn is_zero(&self) -> bool {
self.0.is_zero()
}
Expand All @@ -116,6 +121,9 @@ where
}
}

#[cfg(has_num_saturating)]
impl<T: Zero> Zero for Saturating<T> where Saturating<T>: Add<Output = Saturating<T>> {}

#[cfg(has_num_saturating)]
impl<T: ConstZero> ConstZero for Saturating<T>
where
Expand All @@ -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<Self, Output = Self> {
/// 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
///
Expand All @@ -143,12 +147,12 @@ pub trait One: Sized + Mul<Self, Output = Self> {
// 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
Expand All @@ -162,6 +166,16 @@ pub trait One: Sized + Mul<Self, Output = Self> {
}
}

/// Defines a multiplicative identity element for `Self`.
///
/// # Laws
///
/// ```text
/// a * 1 = a ∀ a ∈ Self
/// 1 * a = a ∀ a ∈ Self
/// ```
pub trait One: PartialOne + Mul<Self, Output = Self> {}

/// Defines an associated constant representing the multiplicative identity
/// element for `Self`.
pub trait ConstOne: One {
Expand All @@ -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
Expand All @@ -182,6 +196,8 @@ macro_rules! one_impl {
}
}

impl One for $t {}

impl ConstOne for $t {
const ONE: Self = $v;
}
Expand All @@ -205,10 +221,7 @@ one_impl!(i128, 1);
one_impl!(f32, 1.0);
one_impl!(f64, 1.0);

impl<T: One> One for Wrapping<T>
where
Wrapping<T>: Mul<Output = Wrapping<T>>,
{
impl<T: PartialOne> PartialOne for Wrapping<T> {
fn set_one(&mut self) {
self.0.set_one();
}
Expand All @@ -218,6 +231,8 @@ where
}
}

impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output = Wrapping<T>> {}

impl<T: ConstOne> ConstOne for Wrapping<T>
where
Wrapping<T>: Mul<Output = Wrapping<T>>,
Expand All @@ -226,10 +241,7 @@ where
}

#[cfg(has_num_saturating)]
impl<T: One> One for Saturating<T>
where
Saturating<T>: Mul<Output = Saturating<T>>,
{
impl<T: PartialOne> PartialOne for Saturating<T> {
fn set_one(&mut self) {
self.0.set_one();
}
Expand All @@ -239,6 +251,9 @@ where
}
}

#[cfg(has_num_saturating)]
impl<T: One> One for Saturating<T> where Saturating<T>: Mul<Output = Saturating<T>> {}

#[cfg(has_num_saturating)]
impl<T: ConstOne> ConstOne for Saturating<T>
where
Expand All @@ -251,14 +266,14 @@ where

/// Returns the additive identity, `0`.
#[inline(always)]
pub fn zero<T: Zero>() -> T {
Zero::zero()
pub fn zero<T: PartialZero>() -> T {
PartialZero::zero()
}

/// Returns the multiplicative identity, `1`.
#[inline(always)]
pub fn one<T: One>() -> T {
One::one()
pub fn one<T: PartialOne>() -> T {
PartialOne::one()
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down