crypto_bigint/uint/
bit_xor.rs
1use super::UInt;
4use crate::{Limb, Wrapping};
5use core::ops::{BitXor, BitXorAssign};
6use subtle::{Choice, CtOption};
7
8impl<const LIMBS: usize> UInt<LIMBS> {
9 #[inline(always)]
11 pub const fn bitxor(&self, rhs: &Self) -> Self {
12 let mut limbs = [Limb::ZERO; LIMBS];
13 let mut i = 0;
14
15 while i < LIMBS {
16 limbs[i] = self.limbs[i].bitxor(rhs.limbs[i]);
17 i += 1;
18 }
19
20 Self { limbs }
21 }
22
23 pub const fn wrapping_xor(&self, rhs: &Self) -> Self {
28 self.bitxor(rhs)
29 }
30
31 pub fn checked_xor(&self, rhs: &Self) -> CtOption<Self> {
33 let result = self.bitxor(rhs);
34 CtOption::new(result, Choice::from(1))
35 }
36}
37
38impl<const LIMBS: usize> BitXor for UInt<LIMBS> {
39 type Output = Self;
40
41 fn bitxor(self, rhs: Self) -> UInt<LIMBS> {
42 self.bitxor(&rhs)
43 }
44}
45
46impl<const LIMBS: usize> BitXor<&UInt<LIMBS>> for UInt<LIMBS> {
47 type Output = UInt<LIMBS>;
48
49 fn bitxor(self, rhs: &UInt<LIMBS>) -> UInt<LIMBS> {
50 (&self).bitxor(rhs)
51 }
52}
53
54impl<const LIMBS: usize> BitXor<UInt<LIMBS>> for &UInt<LIMBS> {
55 type Output = UInt<LIMBS>;
56
57 fn bitxor(self, rhs: UInt<LIMBS>) -> UInt<LIMBS> {
58 self.bitxor(&rhs)
59 }
60}
61
62impl<const LIMBS: usize> BitXor<&UInt<LIMBS>> for &UInt<LIMBS> {
63 type Output = UInt<LIMBS>;
64
65 fn bitxor(self, rhs: &UInt<LIMBS>) -> UInt<LIMBS> {
66 self.bitxor(rhs)
67 }
68}
69
70impl<const LIMBS: usize> BitXorAssign for UInt<LIMBS> {
71 fn bitxor_assign(&mut self, other: Self) {
72 *self = *self ^ other;
73 }
74}
75
76impl<const LIMBS: usize> BitXorAssign<&UInt<LIMBS>> for UInt<LIMBS> {
77 fn bitxor_assign(&mut self, other: &Self) {
78 *self = *self ^ other;
79 }
80}
81
82impl<const LIMBS: usize> BitXor for Wrapping<UInt<LIMBS>> {
83 type Output = Self;
84
85 fn bitxor(self, rhs: Self) -> Wrapping<UInt<LIMBS>> {
86 Wrapping(self.0.bitxor(&rhs.0))
87 }
88}
89
90impl<const LIMBS: usize> BitXor<&Wrapping<UInt<LIMBS>>> for Wrapping<UInt<LIMBS>> {
91 type Output = Wrapping<UInt<LIMBS>>;
92
93 fn bitxor(self, rhs: &Wrapping<UInt<LIMBS>>) -> Wrapping<UInt<LIMBS>> {
94 Wrapping(self.0.bitxor(&rhs.0))
95 }
96}
97
98impl<const LIMBS: usize> BitXor<Wrapping<UInt<LIMBS>>> for &Wrapping<UInt<LIMBS>> {
99 type Output = Wrapping<UInt<LIMBS>>;
100
101 fn bitxor(self, rhs: Wrapping<UInt<LIMBS>>) -> Wrapping<UInt<LIMBS>> {
102 Wrapping(self.0.bitxor(&rhs.0))
103 }
104}
105
106impl<const LIMBS: usize> BitXor<&Wrapping<UInt<LIMBS>>> for &Wrapping<UInt<LIMBS>> {
107 type Output = Wrapping<UInt<LIMBS>>;
108
109 fn bitxor(self, rhs: &Wrapping<UInt<LIMBS>>) -> Wrapping<UInt<LIMBS>> {
110 Wrapping(self.0.bitxor(&rhs.0))
111 }
112}
113
114impl<const LIMBS: usize> BitXorAssign for Wrapping<UInt<LIMBS>> {
115 fn bitxor_assign(&mut self, other: Self) {
116 *self = *self ^ other;
117 }
118}
119
120impl<const LIMBS: usize> BitXorAssign<&Wrapping<UInt<LIMBS>>> for Wrapping<UInt<LIMBS>> {
121 fn bitxor_assign(&mut self, other: &Self) {
122 *self = *self ^ other;
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use crate::U128;
129
130 #[test]
131 fn checked_xor_ok() {
132 let result = U128::ZERO.checked_xor(&U128::ONE);
133 assert_eq!(result.unwrap(), U128::ONE);
134 }
135
136 #[test]
137 fn overlapping_xor_ok() {
138 let result = U128::ZERO.wrapping_xor(&U128::ONE);
139 assert_eq!(result, U128::ONE);
140 }
141}