From 49de5772ae11511555fa045caf8230edf8af17dd Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 16 Jan 2024 10:32:53 -0700 Subject: [PATCH] Uint: change `split_mixed` to accept `self`; make `pub` The `split_mixed` method provides a `const fn`-friendly way to split numbers. This refactors it to be a method that accepts `self` as an argument so it can be called as `uint.split_mixed()` and also exposes it as `pub`, allowing downstream users to use it in `const fn` contexts. A newly added `SplitMixed` bound typechecks the sizes of the outputs to ensure that they're a valid combination, which is the best we can do absent something like `generic_const_exprs`. --- src/uint/from.rs | 9 ++++++--- src/uint/macros.rs | 6 +++--- src/uint/split.rs | 41 ++++++++++++++++++++++------------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/uint/from.rs b/src/uint/from.rs index cb8e54989..7a8037033 100644 --- a/src/uint/from.rs +++ b/src/uint/from.rs @@ -1,6 +1,6 @@ //! `From`-like conversions for [`Uint`]. -use crate::{ConcatMixed, Limb, Uint, WideWord, Word, U128, U64}; +use crate::{ConcatMixed, Limb, SplitMixed, Uint, WideWord, Word, U128, U64}; impl Uint { /// Create a [`Uint`] from a `u8` (const-friendly) @@ -214,9 +214,12 @@ where } } -impl From> for (Uint, Uint) { +impl From> for (Uint, Uint) +where + Uint: SplitMixed, Uint>, +{ fn from(num: Uint) -> (Uint, Uint) { - crate::uint::split::split_mixed(&num) + num.split_mixed() } } diff --git a/src/uint/macros.rs b/src/uint/macros.rs index 6d594db5c..b43ef1a2e 100644 --- a/src/uint/macros.rs +++ b/src/uint/macros.rs @@ -90,7 +90,7 @@ macro_rules! impl_uint_concat_split_mixed { impl $crate::traits::SplitMixed, Uint<{ <$name>::LIMBS - U64::LIMBS * $size }>> for $name { fn split_mixed(&self) -> (Uint<{ U64::LIMBS * $size }>, Uint<{ <$name>::LIMBS - U64::LIMBS * $size }>) { - $crate::uint::split::split_mixed(self) + self.split_mixed() } } }; @@ -128,7 +128,7 @@ macro_rules! impl_uint_concat_split_even { impl $crate::traits::SplitMixed::LIMBS / 2 }>, Uint<{ <$name>::LIMBS / 2 }>> for $name { fn split_mixed(&self) -> (Uint<{ <$name>::LIMBS / 2 }>, Uint<{ <$name>::LIMBS / 2 }>) { - $crate::uint::split::split_mixed(self) + self.split_mixed() } } @@ -140,7 +140,7 @@ macro_rules! impl_uint_concat_split_even { impl $name { /// Split this number in half, returning its low and high components respectively. pub const fn split(&self) -> (Uint<{ <$name>::LIMBS / 2 }>, Uint<{ <$name>::LIMBS / 2 }>) { - $crate::uint::split::split_mixed(self) + self.split_mixed() } } }; diff --git a/src/uint/split.rs b/src/uint/split.rs index 82f9eb47f..e93cb39f5 100644 --- a/src/uint/split.rs +++ b/src/uint/split.rs @@ -1,26 +1,29 @@ -use crate::{Limb, Uint}; +use crate::{Limb, SplitMixed, Uint}; -/// Split this number in half, returning its low and high components respectively. -#[inline] -pub(crate) const fn split_mixed( - n: &Uint, -) -> (Uint, Uint) { - let top = L + H; - let top = if top < O { top } else { O }; - let mut lo = [Limb::ZERO; L]; - let mut hi = [Limb::ZERO; H]; - let mut i = 0; +impl Uint { + /// Split this number into low and high components respectively. + #[inline] + pub const fn split_mixed(&self) -> (Uint, Uint) + where + Self: SplitMixed, Uint>, + { + let top = L + H; + let top = if top < I { top } else { I }; + let mut lo = [Limb::ZERO; L]; + let mut hi = [Limb::ZERO; H]; + let mut i = 0; - while i < top { - if i < L { - lo[i] = n.limbs[i]; - } else { - hi[i - L] = n.limbs[i]; + while i < top { + if i < L { + lo[i] = self.limbs[i]; + } else { + hi[i - L] = self.limbs[i]; + } + i += 1; } - i += 1; - } - (Uint { limbs: lo }, Uint { limbs: hi }) + (Uint { limbs: lo }, Uint { limbs: hi }) + } } #[cfg(test)]