crypto_bigint/limb/
add.rs1use crate::{Checked, CheckedAdd, Limb, WideWord, Word, Wrapping, Zero};
4use core::ops::{Add, AddAssign};
5use subtle::CtOption;
6
7impl Limb {
8 #[inline(always)]
10 pub const fn adc(self, rhs: Limb, carry: Limb) -> (Limb, Limb) {
11 let a = self.0 as WideWord;
12 let b = rhs.0 as WideWord;
13 let carry = carry.0 as WideWord;
14 let ret = a + b + carry;
15 (Limb(ret as Word), Limb((ret >> Self::BITS) as Word))
16 }
17
18 #[inline]
20 pub const fn saturating_add(&self, rhs: Self) -> Self {
21 Limb(self.0.saturating_add(rhs.0))
22 }
23
24 #[inline(always)]
26 pub const fn wrapping_add(&self, rhs: Self) -> Self {
27 Limb(self.0.wrapping_add(rhs.0))
28 }
29}
30
31impl CheckedAdd for Limb {
32 type Output = Self;
33
34 #[inline]
35 fn checked_add(&self, rhs: Self) -> CtOption<Self> {
36 let (result, carry) = self.adc(rhs, Limb::ZERO);
37 CtOption::new(result, carry.is_zero())
38 }
39}
40
41impl Add for Wrapping<Limb> {
42 type Output = Self;
43
44 fn add(self, rhs: Self) -> Wrapping<Limb> {
45 Wrapping(self.0.wrapping_add(rhs.0))
46 }
47}
48
49impl Add<&Wrapping<Limb>> for Wrapping<Limb> {
50 type Output = Wrapping<Limb>;
51
52 fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
53 Wrapping(self.0.wrapping_add(rhs.0))
54 }
55}
56
57impl Add<Wrapping<Limb>> for &Wrapping<Limb> {
58 type Output = Wrapping<Limb>;
59
60 fn add(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> {
61 Wrapping(self.0.wrapping_add(rhs.0))
62 }
63}
64
65impl Add<&Wrapping<Limb>> for &Wrapping<Limb> {
66 type Output = Wrapping<Limb>;
67
68 fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
69 Wrapping(self.0.wrapping_add(rhs.0))
70 }
71}
72
73impl AddAssign for Wrapping<Limb> {
74 fn add_assign(&mut self, other: Self) {
75 *self = *self + other;
76 }
77}
78
79impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> {
80 fn add_assign(&mut self, other: &Self) {
81 *self = *self + other;
82 }
83}
84
85impl Add for Checked<Limb> {
86 type Output = Self;
87
88 fn add(self, rhs: Self) -> Checked<Limb> {
89 Checked(
90 self.0
91 .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
92 )
93 }
94}
95
96impl Add<&Checked<Limb>> for Checked<Limb> {
97 type Output = Checked<Limb>;
98
99 fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
100 Checked(
101 self.0
102 .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
103 )
104 }
105}
106
107impl Add<Checked<Limb>> for &Checked<Limb> {
108 type Output = Checked<Limb>;
109
110 fn add(self, rhs: Checked<Limb>) -> Checked<Limb> {
111 Checked(
112 self.0
113 .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
114 )
115 }
116}
117
118impl Add<&Checked<Limb>> for &Checked<Limb> {
119 type Output = Checked<Limb>;
120
121 fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
122 Checked(
123 self.0
124 .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
125 )
126 }
127}
128
129impl AddAssign for Checked<Limb> {
130 fn add_assign(&mut self, other: Self) {
131 *self = *self + other;
132 }
133}
134
135impl AddAssign<&Checked<Limb>> for Checked<Limb> {
136 fn add_assign(&mut self, other: &Self) {
137 *self = *self + other;
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use crate::{CheckedAdd, Limb};
144
145 #[test]
146 fn adc_no_carry() {
147 let (res, carry) = Limb::ZERO.adc(Limb::ONE, Limb::ZERO);
148 assert_eq!(res, Limb::ONE);
149 assert_eq!(carry, Limb::ZERO);
150 }
151
152 #[test]
153 fn adc_with_carry() {
154 let (res, carry) = Limb::MAX.adc(Limb::ONE, Limb::ZERO);
155 assert_eq!(res, Limb::ZERO);
156 assert_eq!(carry, Limb::ONE);
157 }
158
159 #[test]
160 fn wrapping_add_no_carry() {
161 assert_eq!(Limb::ZERO.wrapping_add(Limb::ONE), Limb::ONE);
162 }
163
164 #[test]
165 fn wrapping_add_with_carry() {
166 assert_eq!(Limb::MAX.wrapping_add(Limb::ONE), Limb::ZERO);
167 }
168
169 #[test]
170 fn checked_add_ok() {
171 let result = Limb::ZERO.checked_add(Limb::ONE);
172 assert_eq!(result.unwrap(), Limb::ONE);
173 }
174
175 #[test]
176 fn checked_add_overflow() {
177 let result = Limb::MAX.checked_add(Limb::ONE);
178 assert!(!bool::from(result.is_some()));
179 }
180}