crypto_bigint/uint/ref_type/
sub.rs1use super::UintRef;
2use crate::Limb;
3use ctutils::Choice;
4
5impl UintRef {
6 #[inline]
8 pub const fn borrowing_sub_assign_limb(&mut self, mut rhs: Limb, mut borrow: Limb) -> Limb {
9 let mut i = 0;
10 while i < self.limbs.len() {
11 (self.limbs[i], borrow) = self.limbs[i].borrowing_sub(rhs, borrow);
12 rhs = Limb::ZERO;
13 i += 1;
14 }
15 borrow
16 }
17
18 #[inline]
24 #[track_caller]
25 pub const fn borrowing_sub_assign(&mut self, rhs: &Self, borrow: Limb) -> Limb {
26 self.borrowing_sub_assign_slice(&rhs.limbs, borrow)
27 }
28
29 #[inline]
35 #[track_caller]
36 pub const fn borrowing_sub_assign_slice(&mut self, rhs: &[Limb], mut borrow: Limb) -> Limb {
37 assert!(
38 self.limbs.len() >= rhs.len(),
39 "length mismatch in borrowing_sub_assign_slice"
40 );
41 let mut i = 0;
42 while i < rhs.len() {
43 (self.limbs[i], borrow) = self.limbs[i].borrowing_sub(rhs[i], borrow);
44 i += 1;
45 }
46 while i < self.limbs.len() {
47 (self.limbs[i], borrow) = self.limbs[i].borrowing_sub(Limb::ZERO, borrow);
48 i += 1;
49 }
50 borrow
51 }
52
53 #[track_caller]
59 pub(crate) const fn conditional_borrowing_sub_assign(
60 &mut self,
61 rhs: &Self,
62 choice: Choice,
63 ) -> Choice {
64 assert!(
65 self.limbs.len() >= rhs.limbs.len(),
66 "length mismatch in conditional_borrowing_sub_assign"
67 );
68 let mask = Limb::select(Limb::ZERO, Limb::MAX, choice);
69 let mut borrow = Limb::ZERO;
70
71 let mut i = 0;
72 while i < rhs.limbs.len() {
73 let masked_rhs = rhs.limbs[i].bitand(mask);
74 (self.limbs[i], borrow) = self.limbs[i].borrowing_sub(masked_rhs, borrow);
75 i += 1;
76 }
77 while i < self.limbs.len() {
78 (self.limbs[i], borrow) = self.limbs[i].borrowing_sub(Limb::ZERO, borrow);
79 i += 1;
80 }
81
82 borrow.lsb_to_choice()
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use crate::{Choice, Limb, UintRef, Unsigned};
89
90 #[test]
91 fn borrowing_sub_assign_mixed() {
92 let mut a = [Limb::MAX];
93 let borrow =
94 UintRef::new_mut(&mut a).borrowing_sub_assign(Limb::MAX.as_uint_ref(), Limb::MAX);
95 assert_eq!((a, borrow), ([Limb::MAX], Limb::MAX));
96
97 let mut a = [Limb::MAX];
98 let borrow = UintRef::new_mut(&mut a)
99 .conditional_borrowing_sub_assign(Limb::MAX.as_uint_ref(), Choice::FALSE);
100 assert_eq!((a, borrow.to_bool()), ([Limb::MAX], false));
101
102 let mut a = [Limb::MAX - Limb::ONE];
103 let borrow = UintRef::new_mut(&mut a)
104 .conditional_borrowing_sub_assign(Limb::MAX.as_uint_ref(), Choice::TRUE);
105 assert_eq!((a, borrow.to_bool()), ([Limb::MAX], true));
106
107 let mut a = [Limb::MAX - Limb::ONE, Limb::ONE];
108 let borrow =
109 UintRef::new_mut(&mut a).borrowing_sub_assign(Limb::MAX.as_uint_ref(), Limb::ZERO);
110 assert_eq!((a, borrow), ([Limb::MAX, Limb::ZERO], Limb::ZERO));
111
112 let mut a = [Limb::MAX - Limb::ONE, Limb::ZERO];
113 let borrow =
114 UintRef::new_mut(&mut a).borrowing_sub_assign(Limb::MAX.as_uint_ref(), Limb::ZERO);
115 assert_eq!((a, borrow), ([Limb::MAX, Limb::MAX], Limb::MAX));
116
117 let mut a = [Limb::MAX - Limb::ONE, Limb::ONE];
118 let borrow = UintRef::new_mut(&mut a)
119 .conditional_borrowing_sub_assign(Limb::MAX.as_uint_ref(), Choice::TRUE);
120 assert_eq!((a, borrow.to_bool()), ([Limb::MAX, Limb::ZERO], false));
121
122 let mut a = [Limb::MAX - Limb::ONE, Limb::ZERO];
123 let borrow = UintRef::new_mut(&mut a)
124 .conditional_borrowing_sub_assign(Limb::MAX.as_uint_ref(), Choice::TRUE);
125 assert_eq!((a, borrow.to_bool()), ([Limb::MAX, Limb::MAX], true));
126 }
127}