Skip to content

Commit

Permalink
Add ZeroConstant and OneConstant traits
Browse files Browse the repository at this point in the history
Adds traits which are alternatives to the more dynamic `Zero`/`One`
traits which are useful for stack-allocated types where it's possible to
define constant values for zero/one.

`ZeroConstant` bounds on `Zero` as a supertrait, and `OneConstant` on
`One`, allowing them to be used as drop-in replacements.

When a type also impls `PartialEq`, then `ZeroConstant` also provides a
blanket impl of `Zero`, and likewise for `OneConstant`/`One`, making
it simple for stack-allocated integers to impl these traits as an
alternative to `Zero`/`One` while still remaining fully compatible.

The internal impls of `Zero`/`One` on the numeric primitive types have
been changed to use these traits, which should be a fully
backwards-compatible change.
  • Loading branch information
tarcieri authored and cuviper committed Feb 8, 2024
1 parent 29c5b46 commit 06c0ee0
Showing 1 changed file with 48 additions and 18 deletions.
66 changes: 48 additions & 18 deletions src/identities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,32 @@ pub trait Zero: Sized + Add<Self, Output = Self> {
fn is_zero(&self) -> bool;
}

/// Defines an associated constant representing the additive identity element
/// for `Self`.
///
/// Types which impl both this trait and [`PartialEq`] will receive a blanket
/// impl of the [`Zero`] trait.
pub trait ZeroConstant: Zero {
/// The additive identity element of `Self`, `0`.
const ZERO: Self;
}

impl<T: ZeroConstant + PartialEq> Zero for T {
#[inline(always)]
fn zero() -> T {
Self::ZERO
}

#[inline(always)]
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}

macro_rules! zero_impl {
($t:ty, $v:expr) => {
impl Zero for $t {
#[inline]
fn zero() -> $t {
$v
}
#[inline]
fn is_zero(&self) -> bool {
*self == $v
}
impl ZeroConstant for $t {
const ZERO: Self = $v;
}
};
}
Expand Down Expand Up @@ -115,17 +130,32 @@ pub trait One: Sized + Mul<Self, Output = Self> {
}
}

/// Defines an associated constant representing the multiplicative identity
/// element for `Self`.
///
/// Types which impl both this trait and [`PartialEq`] will receive a blanket
/// impl of the [`One`] trait.
pub trait OneConstant: One {
/// The multiplicative identity element of `Self`, `1`.
const ONE: Self;
}

impl<T: OneConstant + PartialEq> One for T {
#[inline(always)]
fn one() -> T {
Self::ONE
}

#[inline(always)]
fn is_one(&self) -> bool {
self == &Self::ONE
}
}

macro_rules! one_impl {
($t:ty, $v:expr) => {
impl One for $t {
#[inline]
fn one() -> $t {
$v
}
#[inline]
fn is_one(&self) -> bool {
*self == $v
}
impl OneConstant for $t {
const ONE: Self = $v;
}
};
}
Expand Down

0 comments on commit 06c0ee0

Please sign in to comment.