Advertisement
sword_smith

u64 div_mod using only u32 div_mod

Mar 28th, 2023
1,199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 2.04 KB | Source Code | 0 0
  1. use std::u32;
  2. use std::u64;
  3.  
  4. type U32DivModResult = (u32, u32);
  5. type U64DivModResult = (u64, u64);
  6.  
  7. fn divmod(dividend: u32, divisor: u32) -> U32DivModResult {
  8.     let quotient = dividend / divisor;
  9.     let remainder = dividend % divisor;
  10.     (quotient, remainder)
  11. }
  12.  
  13. fn div_mod_u64_v9(numerator: u64, divisor: u64) -> U64DivModResult {
  14.     let num_hi = (numerator >> 32) as u32;
  15.     let num_lo = (numerator & u32::MAX as u64) as u32;
  16.     let div_hi = (divisor >> 32) as u32;
  17.     let div_lo = (divisor & u32::MAX as u64) as u32;
  18.  
  19.     if div_hi == 0 && num_hi == 0 {
  20.         let (quotient, remainder) = divmod(num_lo, div_lo);
  21.         return (quotient as u64, remainder as u64);
  22.     }
  23.  
  24.     let mut res;
  25.  
  26.     let mut q1 = 0;
  27.     if div_hi != 0 {
  28.         res = divmod(num_hi, div_hi);
  29.         q1 = res.0 as u64;
  30.     }
  31.  
  32.     let mut r1_lo = q1 * div_lo as u64;
  33.     let mut r1_hi = q1 * div_hi as u64 + (r1_lo >> 32);
  34.     r1_lo = r1_lo & u32::MAX as u64;
  35.  
  36.     if r1_hi > num_hi as u64 || (r1_hi == num_hi as u64 && r1_lo > num_lo as u64) {
  37.         q1 -= 1;
  38.         r1_lo = q1 * div_lo as u64;
  39.         r1_hi = q1 * div_hi as u64 + (r1_lo >> 32);
  40.         r1_lo = r1_lo & u32::MAX as u64;
  41.     }
  42.  
  43.     let rem1_hi = num_hi.wrapping_sub(r1_hi as u32);
  44.     let (rem1_lo, borrow) = num_lo.overflowing_sub(r1_lo as u32);
  45.     let rem2 = ((rem1_hi as u64) << 32) | rem1_lo as u64;
  46.     let rem2 = if borrow {
  47.         rem2.wrapping_sub(1 << 32)
  48.     } else {
  49.         rem2
  50.     };
  51.  
  52.     res = divmod((rem2 >> 32) as u32, div_hi);
  53.     let mut q2 = res.0 as u64;
  54.  
  55.     let mut r2_lo = q2 * div_lo as u64;
  56.     let mut r2_hi = q2 * div_hi as u64 + (r2_lo >> 32);
  57.     r2_lo = r2_lo & u32::MAX as u64;
  58.  
  59.     if r2_hi > rem1_hi as u64 || (r2_hi == rem1_hi as u64 && r2_lo > rem1_lo as u64) {
  60.         q2 -= 1;
  61.         r2_lo = q2 * div_lo as u64;
  62.         r2_hi = q2 * div_hi as u64 + (r2_lo >> 32);
  63.         r2_lo = r2_lo & u32::MAX as u64;
  64.     }
  65.  
  66.     let remainder = rem2 - ((r2_hi << 32) | r2_lo);
  67.     let quotient = (q1) + q2;
  68.  
  69.     (quotient, remainder)
  70. }
Tags: u64 division
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement