From 06c0ee035cb12a9d3ed1a32e8fde80c04922417f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 14 Dec 2023 11:55:13 -0700 Subject: [PATCH 1/6] Add `ZeroConstant` and `OneConstant` traits 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. --- src/identities.rs | 66 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index 2486cb19..046c28db 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -28,17 +28,32 @@ pub trait Zero: Sized + Add { 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 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; } }; } @@ -115,17 +130,32 @@ pub trait One: Sized + Mul { } } +/// 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 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; } }; } From 536dcf2588ee12a4934329aa08b01e42ed638cda Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 17 Dec 2023 11:03:20 -0700 Subject: [PATCH 2/6] Remove blanket impls; add impls for `Wrapping` --- src/identities.rs | 60 ++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index 046c28db..ff8bf2ea 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -38,20 +38,19 @@ pub trait ZeroConstant: Zero { const ZERO: Self; } -impl 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; } @@ -92,6 +91,13 @@ where } } +impl ZeroConstant for Wrapping +where + Wrapping: Add>, +{ + const ZERO: Self = Self(T::ZERO); +} + /// Defines a multiplicative identity element for `Self`. /// /// # Laws @@ -140,20 +146,19 @@ pub trait OneConstant: One { const ONE: Self; } -impl 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; } @@ -190,6 +195,13 @@ where } } +impl OneConstant for Wrapping +where + Wrapping: Mul>, +{ + const ONE: Self = Self(T::ONE); +} + // Some helper functions provided for backwards compatibility. /// Returns the additive identity, `0`. From bc42b83117155c84625837ea336691ca119a5b0c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 30 Dec 2023 14:56:39 -0700 Subject: [PATCH 3/6] Rename to ConstZero/ConstOne and re-export from toplevel --- src/identities.rs | 12 ++++++------ src/lib.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index ff8bf2ea..bc6c56a2 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -33,7 +33,7 @@ pub trait Zero: Sized + Add { /// /// Types which impl both this trait and [`PartialEq`] will receive a blanket /// impl of the [`Zero`] trait. -pub trait ZeroConstant: Zero { +pub trait ConstZero: Zero { /// The additive identity element of `Self`, `0`. const ZERO: Self; } @@ -51,7 +51,7 @@ macro_rules! zero_impl { } } - impl ZeroConstant for $t { + impl ConstZero for $t { const ZERO: Self = $v; } }; @@ -91,7 +91,7 @@ where } } -impl ZeroConstant for Wrapping +impl ConstZero for Wrapping where Wrapping: Add>, { @@ -141,7 +141,7 @@ pub trait One: Sized + Mul { /// /// Types which impl both this trait and [`PartialEq`] will receive a blanket /// impl of the [`One`] trait. -pub trait OneConstant: One { +pub trait ConstOne: One { /// The multiplicative identity element of `Self`, `1`. const ONE: Self; } @@ -159,7 +159,7 @@ macro_rules! one_impl { } } - impl OneConstant for $t { + impl ConstOne for $t { const ONE: Self = $v; } }; @@ -195,7 +195,7 @@ where } } -impl OneConstant for Wrapping +impl ConstOne for Wrapping where Wrapping: Mul>, { diff --git a/src/lib.rs b/src/lib.rs index 54dab6e5..9ee16fc8 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, One, Zero}; +pub use crate::identities::{one, zero, ConstOne, ConstZero, One, Zero}; pub use crate::int::PrimInt; pub use crate::ops::bytes::{FromBytes, ToBytes}; pub use crate::ops::checked::{ From e48ffe2118e8733f3715c37319996bd5dbfc59b6 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 31 Dec 2023 11:36:44 -0700 Subject: [PATCH 4/6] Update src/identities.rs --- src/identities.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index bc6c56a2..2e3f1d56 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -30,9 +30,6 @@ pub trait Zero: Sized + Add { /// 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 ConstZero: Zero { /// The additive identity element of `Self`, `0`. const ZERO: Self; From 6ab6de2cf7968dc7e93017ba40eabce5a0920950 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 31 Dec 2023 11:37:11 -0700 Subject: [PATCH 5/6] Update src/identities.rs --- src/identities.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index 2e3f1d56..f0369436 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -135,9 +135,6 @@ pub trait One: Sized + Mul { /// 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 ConstOne: One { /// The multiplicative identity element of `Self`, `1`. const ONE: Self; From 67d9e74acc4920777a5591c8bbc1a907da00b3f3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 7 Feb 2024 16:25:03 -0800 Subject: [PATCH 6/6] Avoid `Self` constructor for `Wrapping` --- src/identities.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/identities.rs b/src/identities.rs index f0369436..c30cd1dc 100644 --- a/src/identities.rs +++ b/src/identities.rs @@ -92,7 +92,7 @@ impl ConstZero for Wrapping where Wrapping: Add>, { - const ZERO: Self = Self(T::ZERO); + const ZERO: Self = Wrapping(T::ZERO); } /// Defines a multiplicative identity element for `Self`. @@ -193,7 +193,7 @@ impl ConstOne for Wrapping where Wrapping: Mul>, { - const ONE: Self = Self(T::ONE); + const ONE: Self = Wrapping(T::ONE); } // Some helper functions provided for backwards compatibility.