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