diff --git a/src/imath.rs b/src/imath.rs index 0c7f8af..e7dcbc3 100644 --- a/src/imath.rs +++ b/src/imath.rs @@ -6,23 +6,17 @@ /// Uses a binary search. #[must_use] pub const fn isqrt(n: u64) -> u64 { - if n == u64::MAX { - return 4_294_967_296; - } - - let mut left = 0; - let mut right = n + 1; - - while left != right - 1 { - let mid = left + (right - left) / 2; - if mid as u128 * mid as u128 <= n as u128 { - left = mid; - } else { - right = mid; + if n <= 1 { + n + } else { + let mut x0 = n / 2; + let mut x1 = (x0 + n / x0) / 2; + while x1 < x0 { + x0 = x1; + x1 = (x0 + n / x0) / 2; } + x0 } - - left } /// Calculates `(base ^ exp) % modulo` without overflow. @@ -64,6 +58,7 @@ mod test { f64::from(u32::MAX).sqrt().floor() as u64, isqrt(u64::from(u32::MAX)) ); - assert_eq!(isqrt(u64::MAX), 4294967296); + assert_eq!(isqrt(u64::MAX - 1), 4294967295); + assert_eq!(isqrt(u64::MAX), 4294967295); } } diff --git a/src/lib.rs b/src/lib.rs index 2392395..751782c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -356,7 +356,7 @@ pub const fn are_prime() -> [bool; N] { pub const fn moebius(mut x: u64) -> i8 { let mut prime_count: u64 = 0; - // If x is divisible by the given factor this macro counts the factor and divides it out. + // If x is divisible by the given factor this macro counts the factor and divides it out. // It then returns zero if x is still divisible by the factor. macro_rules! handle_factors { ($($factor:expr),+) => {