qfall_math/integer/z/logic/
bit_xor.rs

1// Copyright © 2025 Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! This module contains implementations of the [`BitXor`] trait.
10
11use crate::{
12    integer::Z,
13    macros::arithmetics::{
14        arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
15        arithmetic_trait_mixed_borrowed_owned,
16    },
17};
18use flint_sys::fmpz::fmpz_xor;
19use std::ops::BitXor;
20
21impl BitXor for &Z {
22    type Output = Z;
23
24    /// Computes the bit-wise logical `xor` of `self` and `other`.
25    ///
26    /// Parameters:
27    /// - `other`: specifies the value to apply the bit-wise logical `xor` action to
28    ///   apart from `self`
29    ///
30    /// Returns a new instance of [`Z`] containing the number resulting
31    /// from the bit-wise logical `xor` operation performed on `self` and `other`.
32    ///
33    /// # Examples
34    /// ```
35    /// use qfall_math::integer::Z;
36    /// let a = Z::from(5);
37    /// let b = Z::from(7);
38    ///
39    /// let c: Z = &a ^ &b;
40    /// let d: Z = a ^ 2;
41    /// let e: Z = b ^ 15_u64;
42    /// ```
43    fn bitxor(self, other: Self) -> Self::Output {
44        let mut out = Z::default();
45        unsafe { fmpz_xor(&mut out.value, &self.value, &other.value) };
46        out
47    }
48}
49
50arithmetic_trait_borrowed_to_owned!(BitXor, bitxor, Z, Z, Z);
51arithmetic_trait_mixed_borrowed_owned!(BitXor, bitxor, Z, Z, Z);
52arithmetic_between_types!(BitXor, bitxor, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
53
54#[cfg(test)]
55mod test_bitxor {
56    use super::Z;
57    use std::str::FromStr;
58
59    /// Testing `bitxor` for two [`Z`]
60    #[test]
61    fn bitxor() {
62        let a: Z = Z::from(42);
63        let b: Z = Z::from(24);
64
65        let c: Z = a ^ b;
66
67        assert_eq!(Z::from(50), c);
68    }
69
70    /// Testing `bitxor` for two borrowed [`Z`]
71    #[test]
72    fn bitxor_borrow() {
73        let a: Z = Z::from(42);
74        let b: Z = Z::from(24);
75
76        let c: Z = &a ^ &b;
77
78        assert_eq!(Z::from(50), c);
79    }
80
81    /// Testing `bitxor` for borrowed [`Z`] and [`Z`]
82    #[test]
83    fn bitxor_first_borrowed() {
84        let a: Z = Z::from(42);
85        let b: Z = Z::from(24);
86
87        let c: Z = &a ^ b;
88
89        assert_eq!(Z::from(50), c);
90    }
91
92    /// Testing `bitxor` for [`Z`] and borrowed [`Z`]
93    #[test]
94    fn bitxor_second_borrowed() {
95        let a: Z = Z::from(42);
96        let b: Z = Z::from(24);
97
98        let c: Z = a ^ &b;
99
100        assert_eq!(Z::from(50), c);
101    }
102
103    /// Testing `bitxor` for large numbers
104    #[test]
105    fn bitxor_large_numbers() {
106        let a: Z = Z::from(u64::MAX);
107        let b: Z = Z::from(-221319874);
108        let c: Z = Z::from(i64::MIN);
109        let d_cmp = Z::from_str("-18446744073488231743").unwrap();
110        let e_cmp = Z::from_str("-9223372036854775809").unwrap();
111
112        let d: Z = &a ^ b;
113        let e: Z = a ^ c;
114
115        assert_eq!(d_cmp, d);
116        assert_eq!(e_cmp, e);
117    }
118
119    /// Testing `bitxor` between different types
120    #[test]
121    #[allow(clippy::op_ref)]
122    fn availability() {
123        let a: Z = Z::from(42);
124        let b: u64 = 1;
125        let c: u32 = 1;
126        let d: u16 = 1;
127        let e: u8 = 1;
128        let f: i64 = 1;
129        let g: i32 = 1;
130        let h: i16 = 1;
131        let i: i8 = 1;
132
133        let _: Z = &a ^ &b;
134        let _: Z = &a ^ &c;
135        let _: Z = &a ^ &d;
136        let _: Z = &a ^ &e;
137        let _: Z = &a ^ &f;
138        let _: Z = &a ^ &g;
139        let _: Z = &a ^ &h;
140        let _: Z = &a ^ &i;
141
142        let _: Z = &b ^ &a;
143        let _: Z = &c ^ &a;
144        let _: Z = &d ^ &a;
145        let _: Z = &e ^ &a;
146        let _: Z = &f ^ &a;
147        let _: Z = &g ^ &a;
148        let _: Z = &h ^ &a;
149        let _: Z = &i ^ &a;
150
151        let _: Z = &a ^ b;
152        let _: Z = &a ^ c;
153        let _: Z = &a ^ d;
154        let _: Z = &a ^ e;
155        let _: Z = &a ^ f;
156        let _: Z = &a ^ g;
157        let _: Z = &a ^ h;
158        let _: Z = &a ^ i;
159
160        let _: Z = &b ^ Z::from(42);
161        let _: Z = &c ^ Z::from(42);
162        let _: Z = &d ^ Z::from(42);
163        let _: Z = &e ^ Z::from(42);
164        let _: Z = &f ^ Z::from(42);
165        let _: Z = &g ^ Z::from(42);
166        let _: Z = &h ^ Z::from(42);
167        let _: Z = &i ^ Z::from(42);
168
169        let _: Z = Z::from(42) ^ &b;
170        let _: Z = Z::from(42) ^ &c;
171        let _: Z = Z::from(42) ^ &d;
172        let _: Z = Z::from(42) ^ &e;
173        let _: Z = Z::from(42) ^ &f;
174        let _: Z = Z::from(42) ^ &g;
175        let _: Z = Z::from(42) ^ &h;
176        let _: Z = Z::from(42) ^ &i;
177
178        let _: Z = b ^ &a;
179        let _: Z = c ^ &a;
180        let _: Z = d ^ &a;
181        let _: Z = e ^ &a;
182        let _: Z = f ^ &a;
183        let _: Z = g ^ &a;
184        let _: Z = h ^ &a;
185        let _: Z = i ^ &a;
186
187        let _: Z = Z::from(42) ^ b;
188        let _: Z = Z::from(42) ^ c;
189        let _: Z = Z::from(42) ^ d;
190        let _: Z = Z::from(42) ^ e;
191        let _: Z = Z::from(42) ^ f;
192        let _: Z = Z::from(42) ^ g;
193        let _: Z = Z::from(42) ^ h;
194        let _: Z = Z::from(42) ^ i;
195
196        let _: Z = b ^ Z::from(42);
197        let _: Z = c ^ Z::from(42);
198        let _: Z = d ^ Z::from(42);
199        let _: Z = e ^ Z::from(42);
200        let _: Z = f ^ Z::from(42);
201        let _: Z = g ^ Z::from(42);
202        let _: Z = h ^ Z::from(42);
203        let _: Z = i ^ Z::from(42);
204    }
205}