From e620eeed5e1bd76a795cabfb31ee76570cbde3d3 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Mon, 7 Sep 2020 21:08:51 -0700 Subject: [PATCH] Remove impl_isqrt macro The implementation can now just use a normal generic impl. Note that this is tecnically a minor breaking change, as if a user has both: - A custom num_traits::PrimInt impl - A custom IntegerSquareRoot impl Their code will no longer compile Signed-off-by: Joe Richey --- src/lib.rs | 64 +++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9d93c55..1feb1e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,49 +44,39 @@ pub trait IntegerSquareRoot { Self: Sized; } -#[inline(always)] -fn integer_sqrt_impl(mut n: T) -> Option { - use core::cmp::Ordering; - match n.cmp(&T::zero()) { - // Hopefully this will be stripped for unsigned numbers (impossible condition) - Ordering::Less => return None, - Ordering::Equal => return Some(T::zero()), - _ => {} - } - - // Compute bit, the largest power of 4 <= n - let max_shift: u32 = T::zero().leading_zeros() - 1; - let shift: u32 = (max_shift - n.leading_zeros()) & !1; - let mut bit = T::one().unsigned_shl(shift); - - // Algorithm based on the implementation in: - // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2) - // Note that result/bit are logically unsigned (even if T is signed). - let mut result = T::zero(); - while bit != T::zero() { - if n >= (result + bit) { - n = n - (result + bit); - result = result.unsigned_shr(1) + bit; - } else { - result = result.unsigned_shr(1); +impl IntegerSquareRoot for T { + fn integer_sqrt_checked(&self) -> Option { + use core::cmp::Ordering; + match self.cmp(&T::zero()) { + // Hopefully this will be stripped for unsigned numbers (impossible condition) + Ordering::Less => return None, + Ordering::Equal => return Some(T::zero()), + _ => {} } - bit = bit.unsigned_shr(2); - } - Some(result) -} -macro_rules! impl_isqrt { - ($($t:ty)*) => { $( - impl IntegerSquareRoot for $t { - fn integer_sqrt_checked(&self) -> Option { - integer_sqrt_impl(*self) + // Compute bit, the largest power of 4 <= n + let max_shift: u32 = T::zero().leading_zeros() - 1; + let shift: u32 = (max_shift - self.leading_zeros()) & !1; + let mut bit = T::one().unsigned_shl(shift); + + // Algorithm based on the implementation in: + // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2) + // Note that result/bit are logically unsigned (even if T is signed). + let mut n = *self; + let mut result = T::zero(); + while bit != T::zero() { + if n >= (result + bit) { + n = n - (result + bit); + result = result.unsigned_shr(1) + bit; + } else { + result = result.unsigned_shr(1); } + bit = bit.unsigned_shr(2); } - )* }; + Some(result) + } } -impl_isqrt!(usize u128 u64 u32 u16 u8 isize i128 i64 i32 i16 i8); - #[cfg(test)] mod tests { use super::IntegerSquareRoot;