port sqrt optimization to u128 case
authoralfadur
Mon, 14 Mar 2022 22:08:31 +0300
changeset 15837 42109eb6ef51
parent 15836 f7875779d910
child 15838 c910381d1ea9
port sqrt optimization to u128 case
rust/fpnum/src/lib.rs
--- a/rust/fpnum/src/lib.rs	Mon Mar 14 10:12:00 2022 +0100
+++ b/rust/fpnum/src/lib.rs	Mon Mar 14 22:08:31 2022 +0300
@@ -473,7 +473,7 @@
 bin_assign_op_impl!(FPPoint, ops::DivAssign<FPNum>, div_assign, /);
 
 pub fn integral_sqrt(value: u64) -> u64 {
-    let mut digits = (64u32 - 1).saturating_sub(value.leading_zeros()) & 0xFFFF_FFFE;
+    let mut digits = (64u32 - 1).saturating_sub(value.leading_zeros()) & 0xFE;
     let mut result = if value == 0 { 0u64 } else { 1u64 };
 
     while digits != 0 {
@@ -488,20 +488,17 @@
 }
 
 pub fn integral_sqrt_ext(mut value: u128) -> u128 {
-    let mut digit_sqr =
-        0x40000000_00000000_00000000_00000000u128.wrapping_shr(value.leading_zeros() & 0xFFFF_FFFE);
-    let mut result = 0u128;
+    let mut digits = (128u32 - 1).saturating_sub(value.leading_zeros()) & 0xFE;
+    let mut result = if value == 0 { 0u128 } else { 1u128 };
 
-    while digit_sqr != 0 {
-        let approx = result + digit_sqr;
-        result >>= 1;
+    while digits != 0 {
+        result <<= 1;
+        if (result + 1).pow(2) <= value >> (digits - 2) {
+            result += 1;
+        }
+        digits -= 2;
+    }
 
-        if approx <= value {
-            value -= approx;
-            result += digit_sqr;
-        }
-        digit_sqr >>= 2;
-    }
     result
 }