Skip to content

Commit

Permalink
Introduce Int::full_limb_shr
Browse files Browse the repository at this point in the history
  • Loading branch information
erik-3milabs committed Jan 24, 2025
1 parent dc82ee8 commit 1c98833
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/uint/shr.rs
Original file line number Diff line number Diff line change
@@ -75,6 +75,51 @@ impl<const LIMBS: usize> Uint<LIMBS> {
result
}

/// Compute `self >> (Limb::BITS * limb_shift)`, for `limb_shift < Self::LIMBS`.
///
/// Returns `None` if `limb_shift >= Self::LIMBS`.
#[inline(always)]
pub const fn full_limb_shr(&self, limb_shift: u32) -> ConstCtOption<Self> {
let shift_bits = u32::BITS - (LIMBS as u32 - 1).leading_zeros();
let overflow = ConstChoice::from_u32_lt(limb_shift, LIMBS as u32).not();
let limb_shift = limb_shift % LIMBS as u32;

let mut result = *self;
let mut i = 0;

// Speed up shifting upto 8 limbs.
while i <= 3 && (1 << i) <= 2 * LIMBS {
let bit = ConstChoice::from_u32_lsb((limb_shift >> i) & 1);

let mut j = 0;
let limbs = result.as_limbs_mut();
let offset = 1 << i;
while j < Self::LIMBS.saturating_sub(offset) {
limbs[j] = Limb::select(limbs[j], limbs[j + offset], bit);
j += 1;
}
while j < Self::LIMBS {
limbs[j] = Limb::select(limbs[j], Limb::ZERO, bit);
j += 1;
}

i += 1;
}
while i < shift_bits {
let bit = ConstChoice::from_u32_lsb((limb_shift >> i) & 1);
result = Uint::select(
&result,
&result
.overflowing_shr_vartime(Limb::BITS << i)
.expect("shift within range"),
bit,
);
i += 1;
}

ConstCtOption::new(Uint::select(&result, &Self::ZERO, overflow), overflow.not())
}

/// Computes `self >> shift`.
///
/// Returns `None` if `shift >= Self::BITS`.

0 comments on commit 1c98833

Please sign in to comment.