crypto_bigint/uint/ref_type/
add.rs1use super::UintRef;
2use crate::{Choice, Limb};
3
4impl UintRef {
5 #[inline]
7 pub const fn add_assign_limb(&mut self, mut rhs: Limb) -> Limb {
8 let mut i = 0;
9 while i < self.limbs.len() {
10 (self.limbs[i], rhs) = self.limbs[i].overflowing_add(rhs);
11 i += 1;
12 }
13 rhs
14 }
15
16 #[inline]
21 #[track_caller]
22 pub const fn carrying_add_assign(&mut self, rhs: &Self, carry: Limb) -> Limb {
23 self.carrying_add_assign_slice(&rhs.limbs, carry)
24 }
25
26 #[inline]
31 #[track_caller]
32 pub const fn carrying_add_assign_slice(&mut self, rhs: &[Limb], mut carry: Limb) -> Limb {
33 assert!(
34 self.limbs.len() >= rhs.len(),
35 "length mismatch in carrying_add_assign_slice"
36 );
37 let mut i = 0;
38 while i < rhs.len() {
39 (self.limbs[i], carry) = self.limbs[i].carrying_add(rhs[i], carry);
40 i += 1;
41 }
42 while i < self.limbs.len() {
43 (self.limbs[i], carry) = self.limbs[i].overflowing_add(carry);
44 i += 1;
45 }
46 carry
47 }
48
49 #[inline]
54 #[track_caller]
55 pub const fn conditional_add_assign(
56 &mut self,
57 rhs: &Self,
58 carry: Limb,
59 choice: Choice,
60 ) -> Limb {
61 self.conditional_add_assign_slice(rhs.as_limbs(), carry, choice)
62 }
63
64 #[inline]
69 #[track_caller]
70 pub const fn conditional_add_assign_slice(
71 &mut self,
72 rhs: &[Limb],
73 mut carry: Limb,
74 choice: Choice,
75 ) -> Limb {
76 assert!(
77 self.limbs.len() >= rhs.len(),
78 "length mismatch in conditional_add_assign_slice"
79 );
80 let mut i = 0;
81 while i < rhs.len() {
82 (self.limbs[i], carry) =
83 self.limbs[i].carrying_add(Limb::select(Limb::ZERO, rhs[i], choice), carry);
84 i += 1;
85 }
86 while i < self.limbs.len() {
87 (self.limbs[i], carry) = self.limbs[i].overflowing_add(carry);
88 i += 1;
89 }
90 carry
91 }
92
93 #[inline]
99 #[track_caller]
100 pub const fn carrying_add_assign_mul_limb(
101 &mut self,
102 rhs: &Self,
103 rhs_mul: Limb,
104 mut carry: Limb,
105 ) -> Limb {
106 assert!(
107 self.limbs.len() >= rhs.limbs.len(),
108 "length mismatch in carrying_add_assign_mul_limb"
109 );
110 let mut i = 0;
111 while i < rhs.limbs.len() {
112 (self.limbs[i], carry) = rhs.limbs[i].carrying_mul_add(rhs_mul, self.limbs[i], carry);
113 i += 1;
114 }
115 self.trailing_mut(i).add_assign_limb(carry)
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use crate::{Choice, Limb, UintRef, Unsigned};
122
123 #[test]
124 fn carrying_add_assign_mixed() {
125 let mut a = [Limb::MAX];
126 let carry =
127 UintRef::new_mut(&mut a).carrying_add_assign(Limb::ONE.as_uint_ref(), Limb::ZERO);
128 assert_eq!((a, carry), ([Limb::ZERO], Limb::ONE));
129
130 let mut a = [Limb::MAX];
131 let carry = UintRef::new_mut(&mut a).conditional_add_assign(
132 Limb::ONE.as_uint_ref(),
133 Limb::ZERO,
134 Choice::FALSE,
135 );
136 assert_eq!((a, carry), ([Limb::MAX], Limb::ZERO));
137
138 let mut a = [Limb::MAX];
139 let carry = UintRef::new_mut(&mut a).conditional_add_assign(
140 Limb::ONE.as_uint_ref(),
141 Limb::ZERO,
142 Choice::TRUE,
143 );
144 assert_eq!((a, carry), ([Limb::ZERO], Limb::ONE));
145
146 let mut a = [Limb::MAX, Limb::MAX];
147 let carry =
148 UintRef::new_mut(&mut a).carrying_add_assign(Limb::ZERO.as_uint_ref(), Limb::ONE);
149 assert_eq!((a, carry), ([Limb::ZERO, Limb::ZERO], Limb::ONE));
150
151 let mut a = [Limb::MAX, Limb::MAX];
152 let carry = UintRef::new_mut(&mut a).conditional_add_assign(
153 Limb::MAX.as_uint_ref(),
154 Limb::ONE,
155 Choice::TRUE,
156 );
157 assert_eq!((a, carry), ([Limb::MAX, Limb::ZERO], Limb::ONE));
158 }
159}