]> git.proxmox.com Git - rustc.git/blob - vendor/crypto-bigint/src/limb/add.rs
New upstream version 1.70.0+dfsg2
[rustc.git] / vendor / crypto-bigint / src / limb / add.rs
1 //! Limb addition
2
3 use crate::{Checked, CheckedAdd, Limb, WideWord, Word, Wrapping, Zero};
4 use core::ops::{Add, AddAssign};
5 use subtle::CtOption;
6
7 impl Limb {
8 /// Computes `self + rhs + carry`, returning the result along with the new carry.
9 #[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::BIT_SIZE) as Word))
16 }
17
18 /// Perform saturating addition.
19 #[inline]
20 pub const fn saturating_add(&self, rhs: Self) -> Self {
21 Limb(self.0.saturating_add(rhs.0))
22 }
23
24 /// Perform wrapping addition, discarding overflow.
25 #[inline(always)]
26 pub const fn wrapping_add(&self, rhs: Self) -> Self {
27 Limb(self.0.wrapping_add(rhs.0))
28 }
29 }
30
31 impl 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
41 impl 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
49 impl 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
57 impl 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
65 impl 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
73 impl AddAssign for Wrapping<Limb> {
74 fn add_assign(&mut self, other: Self) {
75 *self = *self + other;
76 }
77 }
78
79 impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> {
80 fn add_assign(&mut self, other: &Self) {
81 *self = *self + other;
82 }
83 }
84
85 impl 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
96 impl 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
107 impl 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
118 impl 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
129 impl AddAssign for Checked<Limb> {
130 fn add_assign(&mut self, other: Self) {
131 *self = *self + other;
132 }
133 }
134
135 impl AddAssign<&Checked<Limb>> for Checked<Limb> {
136 fn add_assign(&mut self, other: &Self) {
137 *self = *self + other;
138 }
139 }
140
141 #[cfg(test)]
142 mod 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 }