Skip to main content

crypto_bigint/uint/ref_type/
sub.rs

1use super::UintRef;
2use crate::Limb;
3use ctutils::Choice;
4
5impl UintRef {
6    /// Perform an in-place borrowing subtraction of another [`UintRef`], returning the carried limb
7    /// value.
8    #[inline]
9    pub const fn borrowing_sub_assign(&mut self, rhs: &Self, borrow: Limb) -> Limb {
10        self.borrowing_sub_assign_slice(&rhs.limbs, borrow)
11    }
12
13    /// Perform an in-place borrowing subtraction of another limb slice, returning the borrowed limb
14    /// value.
15    ///
16    /// # Panics
17    /// If `self` and `rhs` have different lengths.
18    #[inline]
19    pub const fn borrowing_sub_assign_slice(&mut self, rhs: &[Limb], mut borrow: Limb) -> Limb {
20        assert!(self.limbs.len() == rhs.len(), "length mismatch");
21        let mut i = 0;
22        while i < self.limbs.len() {
23            (self.limbs[i], borrow) = self.limbs[i].borrowing_sub(rhs[i], borrow);
24            i += 1;
25        }
26        borrow
27    }
28
29    /// Perform in-place wrapping subtraction, returning the truthy value as the second element of
30    /// the tuple if an underflow has occurred.
31    pub(crate) fn conditional_borrowing_sub_assign(
32        &mut self,
33        rhs: &Self,
34        choice: Choice,
35    ) -> Choice {
36        debug_assert!(self.bits_precision() <= rhs.bits_precision());
37        let mask = Limb::select(Limb::ZERO, Limb::MAX, choice);
38        let mut borrow = Limb::ZERO;
39
40        for i in 0..self.nlimbs() {
41            let masked_rhs = *rhs.limbs.get(i).unwrap_or(&Limb::ZERO) & mask;
42            let (limb, b) = self.limbs[i].borrowing_sub(masked_rhs, borrow);
43            self.limbs[i] = limb;
44            borrow = b;
45        }
46
47        borrow.lsb_to_choice()
48    }
49}