malachite_nz/integer/logic/
xor.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5//      Copyright © 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012, 2015-2018 Free Software
6//      Foundation, Inc.
7//
8// This file is part of Malachite.
9//
10// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
11// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
12// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
13
14use crate::integer::Integer;
15use crate::natural::InnerNatural::{Large, Small};
16use crate::natural::Natural;
17use crate::natural::arithmetic::add::{
18    limbs_add_limb, limbs_add_limb_to_out, limbs_slice_add_limb_in_place,
19};
20use crate::natural::arithmetic::sub::{
21    limbs_sub, limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb,
22    limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_vec_sub_in_place_right,
23};
24use crate::natural::logic::not::limbs_not_in_place;
25use crate::platform::Limb;
26use alloc::vec::Vec;
27use core::cmp::{Ordering::*, max};
28use core::ops::{BitXor, BitXorAssign};
29use itertools::repeat_n;
30use malachite_base::num::arithmetic::traits::WrappingNegAssign;
31use malachite_base::num::basic::traits::Zero;
32use malachite_base::slices::{slice_leading_zeros, slice_set_zero, slice_test_zero};
33
34// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
35// `Integer`, returns the limbs of the bitwise xor of the `Integer` and a `Limb`. `xs` cannot be
36// empty or only contain zeros.
37//
38// # Worst-case complexity
39// $T(n) = O(n)$
40//
41// $M(n) = O(n)$
42//
43// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
44pub_test! {limbs_neg_xor_limb(xs: &[Limb], y: Limb) -> Vec<Limb> {
45    if y == 0 {
46        return xs.to_vec();
47    }
48    let head = xs[0];
49    let tail = &xs[1..];
50    let mut out = Vec::with_capacity(xs.len());
51    if head != 0 {
52        let head = head.wrapping_neg() ^ y;
53        if head == 0 {
54            out.push(0);
55            out.extend_from_slice(&limbs_add_limb(tail, 1));
56        } else {
57            out.push(head.wrapping_neg());
58            out.extend_from_slice(tail);
59        }
60    } else {
61        out.push(y.wrapping_neg());
62        out.extend_from_slice(&limbs_sub_limb(tail, 1).0);
63    }
64    out
65}}
66
67// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
68// `Integer`, writes the limbs of the bitwise and of the `Integer`, writes the limbs of the bitwise
69// xor of the `Integer` and a `Limb` to an output slice. The output slice must be at least as long
70// as the input slice. `xs` cannot be empty or only contain zeros. Returns whether a carry occurs.
71//
72// # Worst-case complexity
73// $T(n) = O(n)$
74//
75// $M(n) = O(1)$
76//
77// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
78pub_test! {limbs_neg_xor_limb_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) -> bool {
79    let len = xs.len();
80    assert!(out.len() >= len);
81    if y == 0 {
82        out[..len].copy_from_slice(xs);
83        return false;
84    }
85    let head = xs[0];
86    let tail = &xs[1..];
87    if head != 0 {
88        let head = head.wrapping_neg() ^ y;
89        if head == 0 {
90            out[0] = 0;
91            limbs_add_limb_to_out(&mut out[1..len], tail, 1)
92        } else {
93            out[0] = head.wrapping_neg();
94            out[1..len].copy_from_slice(tail);
95            false
96        }
97    } else {
98        out[0] = y.wrapping_neg();
99        limbs_sub_limb_to_out(&mut out[1..len], tail, 1);
100        false
101    }
102}}
103
104// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
105// `Integer`, writes the limbs of the bitwise xor of the `Integer` and a `Limb` to the input slice.
106// `xs` cannot be empty or only contain zeros. Returns whether a carry occurs.
107//
108// # Worst-case complexity
109// $T(n) = O(n)$
110//
111// $M(n) = O(1)$
112//
113// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
114pub_test! {limbs_slice_neg_xor_limb_in_place(xs: &mut [Limb], y: Limb) -> bool {
115    if y == 0 {
116        return false;
117    }
118    let (head, tail) = xs.split_at_mut(1);
119    let head = &mut head[0];
120    if *head != 0 {
121        *head = head.wrapping_neg() ^ y;
122        if *head == 0 {
123            limbs_slice_add_limb_in_place(tail, 1)
124        } else {
125            head.wrapping_neg_assign();
126            false
127        }
128    } else {
129        *head = y.wrapping_neg();
130        limbs_sub_limb_in_place(tail, 1);
131        false
132    }
133}}
134
135// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of the negative of an
136// `Integer`, writes the limbs of the bitwise xor of the `Integer` and a `Limb` to the input slice.
137// `xs` cannot be empty or only contain zeros. If a carry occurs, extends the `Vec`.
138//
139// # Worst-case complexity
140// $T(n) = O(n)$
141//
142// $M(n) = O(1)$
143//
144// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
145pub_test! {limbs_vec_neg_xor_limb_in_place(xs: &mut Vec<Limb>, y: Limb) {
146    if limbs_slice_neg_xor_limb_in_place(xs, y) {
147        xs.push(1);
148    }
149}}
150
151// Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, returns the
152// limbs of the bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y`
153// and whose other limbs are full of `true` bits. `xs` may not be empty.
154//
155// # Worst-case complexity
156// $T(n) = O(n)$
157//
158// $M(n) = O(n)$
159//
160// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
161//
162// # Panics
163// Panics if `xs` is empty.
164pub_test! {limbs_pos_xor_limb_neg(xs: &[Limb], y: Limb) -> Vec<Limb> {
165    let (head, tail) = xs.split_first().unwrap();
166    let lo = head ^ y;
167    let mut out;
168    if lo == 0 {
169        out = limbs_add_limb(tail, 1);
170        out.insert(0, 0);
171    } else {
172        out = xs.to_vec();
173        out[0] = lo.wrapping_neg();
174    }
175    out
176}}
177
178// Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, writes the
179// limbs of the bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y`
180// and whose other limbs are full of `true` bits to an output slice. `xs` may not be empty or only
181// contain zeros. The output slice must be at least as long as the input slice. Returns whether
182// there is a carry.
183//
184// # Worst-case complexity
185// $T(n) = O(n)$
186//
187// $M(n) = O(1)$
188//
189// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
190//
191// # Panics
192// Panics if `xs` is empty or if `out` is shorter than `xs`.
193pub_test! {limbs_pos_xor_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) -> bool {
194    let (head, tail) = xs.split_first().unwrap();
195    let (out_head, out_tail) = out[..xs.len()].split_first_mut().unwrap();
196    let lo = head ^ y;
197    if lo == 0 {
198        *out_head = 0;
199        limbs_add_limb_to_out(out_tail, tail, 1)
200    } else {
201        *out_head = lo.wrapping_neg();
202        out_tail.copy_from_slice(tail);
203        false
204    }
205}}
206
207// Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, takes the
208// bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y` and whose
209// other limbs are full of `true` bits, in place. `xs` may not be empty. Returns whether there is a
210// carry.
211//
212// # Worst-case complexity
213// $T(n) = O(n)$
214//
215// $M(n) = O(1)$
216//
217// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
218//
219// # Panics
220// Panics if `xs` is empty.
221pub_test! {limbs_slice_pos_xor_limb_neg_in_place(xs: &mut [Limb], y: Limb) -> bool {
222    let (head, tail) = xs.split_at_mut(1);
223    let head = &mut head[0];
224    *head ^= y;
225    if *head == 0 {
226        limbs_slice_add_limb_in_place(tail, 1)
227    } else {
228        *head = head.wrapping_neg();
229        false
230    }
231}}
232
233// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of an `Integer`, takes the
234// bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y` and whose
235// other limbs are full of `true` bits, in place. `xs` may not be empty.
236//
237// # Worst-case complexity
238// $T(n) = O(n)$
239//
240// $M(n) = O(1)$
241//
242// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
243//
244// # Panics
245// Panics if `xs` is empty.
246pub_test! {limbs_vec_pos_xor_limb_neg_in_place(xs: &mut Vec<Limb>, y: Limb) {
247    if limbs_slice_pos_xor_limb_neg_in_place(xs, y) {
248        xs.push(1);
249    }
250}}
251
252// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
253// `Integer`, returns the limbs of the bitwise xor of the `Integer` and a negative number whose
254// lowest limb is given by `y` and whose other limbs are full of `true` bits. `xs` may not be empty
255// or only contain zeros.
256//
257// # Worst-case complexity
258// $T(n) = O(n)$
259//
260// $M(n) = O(n)$
261//
262// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
263//
264// # Panics
265// Panics if `xs` is empty or only contains zeros.
266pub_test! {limbs_neg_xor_limb_neg(xs: &[Limb], y: Limb) -> Vec<Limb> {
267    let mut out;
268    if xs[0] == 0 {
269        let carry;
270        (out, carry) = limbs_sub_limb(xs, 1);
271        assert!(!carry);
272        out[0] = y;
273    } else {
274        out = xs.to_vec();
275        out[0] = xs[0].wrapping_neg() ^ y;
276    }
277    out
278}}
279
280// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
281// `Integer`, writes the limbs of the bitwise xor of the `Integer` and a negative number whose
282// lowest limb is given by `y` and whose other limbs are full of `true` bits to an output slice.
283// `xs` may not be empty or only contain zeros. The output slice must be at least as long as the
284// input slice.
285//
286// # Worst-case complexity
287// $T(n) = O(n)$
288//
289// $M(n) = O(1)$
290//
291// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
292//
293// # Panics
294// Panics if `xs` is empty or only contains zeros, or if `out` is shorter than `xs`.
295pub_test! {limbs_neg_xor_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) {
296    let (head, tail) = xs.split_first().unwrap();
297    let (out_head, out_tail) = out[..xs.len()].split_first_mut().unwrap();
298    if *head == 0 {
299        *out_head = y;
300        assert!(!limbs_sub_limb_to_out(out_tail, tail, 1));
301    } else {
302        *out_head = xs[0].wrapping_neg() ^ y;
303        out_tail.copy_from_slice(tail);
304    }
305}}
306
307// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of the negative of an
308// `Integer`, takes the bitwise xor of the `Integer` and a negative number whose lowest limb is
309// given by `y` and whose other limbs are full of `true` bits, in place. `xs` may not be empty or
310// only contain zeros.
311//
312// # Worst-case complexity
313// $T(n) = O(n)$
314//
315// $M(n) = O(1)$
316//
317// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
318//
319// # Panics
320// Panics if `xs` is empty or only contains zeros.
321pub_test! {limbs_neg_xor_limb_neg_in_place(xs: &mut [Limb], y: Limb) {
322    let (head, tail) = xs.split_first_mut().unwrap();
323    if *head == 0 {
324        assert!(!limbs_sub_limb_in_place(tail, 1));
325        *head = y;
326    } else {
327        head.wrapping_neg_assign();
328        *head ^= y;
329    }
330}}
331
332const fn limbs_xor_pos_neg_helper(x: Limb, boundary_seen: &mut bool) -> Limb {
333    if *boundary_seen {
334        !x
335    } else if x == 0 {
336        0
337    } else {
338        *boundary_seen = true;
339        x.wrapping_neg()
340    }
341}
342
343// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
344// negative of another, returns the limbs of the bitwise xor of the `Integer`s. `xs` and `ys` may
345// not be empty or only contain zeros.
346//
347// # Worst-case complexity
348// $T(n) = O(n)$
349//
350// $M(n) = O(n)$
351//
352// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
353//
354// # Panics
355// Panics if `xs` or `ys` are empty or contain only zeros.
356//
357// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res` is returned, the first
358// input is positive, and the second is negative.
359pub_test! {limbs_xor_pos_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
360    let xs_len = xs.len();
361    let ys_len = ys.len();
362    let x_i = slice_leading_zeros(xs);
363    let y_i = slice_leading_zeros(ys);
364    assert!(x_i < xs_len);
365    assert!(y_i < ys_len);
366    if y_i >= xs_len {
367        let mut out = vec![0; x_i];
368        out.push(xs[x_i].wrapping_neg());
369        out.extend(xs[x_i + 1..].iter().map(|x| !x));
370        out.extend(repeat_n(Limb::MAX, y_i - xs_len));
371        out.push(ys[y_i] - 1);
372        out.extend_from_slice(&ys[y_i + 1..]);
373        return out;
374    } else if x_i >= ys_len {
375        let mut out = ys.to_vec();
376        out.extend_from_slice(&xs[ys_len..]);
377        return out;
378    }
379    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
380    let mut out = vec![0; min_i];
381    let mut boundary_seen = false;
382    let x = match x_i.cmp(&y_i) {
383        Equal => {
384            limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen)
385        }
386        Less => {
387            boundary_seen = true;
388            out.push(xs[x_i].wrapping_neg());
389            out.extend(xs[x_i + 1..y_i].iter().map(|x| !x));
390            xs[y_i] ^ (ys[y_i] - 1)
391        }
392        Greater => {
393            boundary_seen = true;
394            out.extend_from_slice(&ys[y_i..x_i]);
395            xs[x_i] ^ ys[x_i]
396        }
397    };
398    out.push(x);
399    let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter());
400    if boundary_seen {
401        out.extend(xys.map(|(x, y)| x ^ y));
402    } else {
403        for (&x, &y) in xys {
404            out.push(limbs_xor_pos_neg_helper(x ^ !y, &mut boundary_seen));
405        }
406    }
407    if xs_len != ys_len {
408        let zs = if xs_len > ys_len {
409            &xs[ys_len..]
410        } else {
411            &ys[xs_len..]
412        };
413        if boundary_seen {
414            out.extend_from_slice(zs);
415        } else {
416            for &z in zs {
417                out.push(limbs_xor_pos_neg_helper(!z, &mut boundary_seen));
418            }
419        }
420    }
421    if slice_test_zero(&out) {
422        out.push(1);
423    }
424    out
425}}
426
427// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
428// negative of another, writes the limbs of the bitwise xor of the `Integer`s to an output slice.
429// `xs` and `ys` may not be empty or only contain zeros. The output slice must be at least as long
430// as the longer of the two input slices. max(`xs.len()`, `ys.len()`) limbs will be written; if the
431// number of significant limbs of the result is lower, some of the written limbs will be zero.
432//
433// Returns whether there is a carry.
434//
435// # Worst-case complexity
436// $T(n) = O(n)$
437//
438// $M(n) = O(1)$
439//
440// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
441//
442// # Panics
443// Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of
444// `xs` and `ys`.
445//
446// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where the first input is positive
447// and the second is negative.
448pub_test! {limbs_xor_pos_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool {
449    let xs_len = xs.len();
450    let ys_len = ys.len();
451    assert!(out.len() >= xs_len);
452    assert!(out.len() >= ys_len);
453    let x_i = slice_leading_zeros(xs);
454    let y_i = slice_leading_zeros(ys);
455    assert!(x_i < xs_len);
456    assert!(y_i < ys_len);
457    if y_i >= xs_len {
458        slice_set_zero(&mut out[..x_i]);
459        out[x_i] = xs[x_i].wrapping_neg();
460        for (out, &x) in out[x_i + 1..xs_len].iter_mut().zip(xs[x_i + 1..].iter()) {
461            *out = !x;
462        }
463        for out in &mut out[xs_len..y_i] {
464            *out = Limb::MAX;
465        }
466        out[y_i] = ys[y_i] - 1;
467        out[y_i + 1..ys_len].copy_from_slice(&ys[y_i + 1..]);
468        return false;
469    } else if x_i >= ys_len {
470        out[..ys_len].copy_from_slice(ys);
471        out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]);
472        return false;
473    }
474    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
475    slice_set_zero(&mut out[..min_i]);
476    let mut boundary_seen = false;
477    match x_i.cmp(&y_i) {
478        Equal => {
479            out[x_i] =
480                limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen);
481        }
482        Less => {
483            boundary_seen = true;
484            out[x_i] = xs[x_i].wrapping_neg();
485            for (out, &x) in out[x_i + 1..y_i].iter_mut().zip(xs[x_i + 1..y_i].iter()) {
486                *out = !x;
487            }
488            out[y_i] = xs[y_i] ^ (ys[y_i] - 1);
489        }
490        Greater => {
491            boundary_seen = true;
492            out[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
493            out[x_i] = xs[x_i] ^ ys[x_i];
494        }
495    }
496    let xys = out[max_i + 1..]
497        .iter_mut()
498        .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()));
499    if boundary_seen {
500        for (out, (&x, &y)) in xys {
501            *out = x ^ y;
502        }
503    } else {
504        for (out, (&x, &y)) in xys {
505            *out = limbs_xor_pos_neg_helper(x ^ !y, &mut boundary_seen);
506        }
507    }
508    let max_len = max(xs_len, ys_len);
509    if xs_len != ys_len {
510        let (min_len, zs) = if max_len == xs_len {
511            (ys_len, &xs[ys_len..])
512        } else {
513            (xs_len, &ys[xs_len..])
514        };
515        if boundary_seen {
516            out[min_len..max_len].copy_from_slice(zs);
517        } else {
518            for (out, &z) in out[min_len..].iter_mut().zip(zs.iter()) {
519                *out = limbs_xor_pos_neg_helper(!z, &mut boundary_seen);
520            }
521        }
522    }
523    slice_test_zero(&out[..max_len])
524}}
525
526fn limbs_xor_pos_neg_in_place_left_helper(
527    xs: &mut [Limb],
528    ys: &[Limb],
529    x_i: usize,
530    y_i: usize,
531) -> bool {
532    let max_i = max(x_i, y_i);
533    let mut boundary_seen = false;
534    match x_i.cmp(&y_i) {
535        Equal => {
536            xs[x_i] =
537                limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen);
538        }
539        Less => {
540            boundary_seen = true;
541            xs[x_i].wrapping_neg_assign();
542            limbs_not_in_place(&mut xs[x_i + 1..y_i]);
543            xs[y_i] ^= ys[y_i] - 1;
544        }
545        Greater => {
546            boundary_seen = true;
547            xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
548            xs[x_i] ^= ys[x_i];
549        }
550    }
551    let xys = xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter());
552    if boundary_seen {
553        for (x, &y) in xys {
554            *x ^= y;
555        }
556    } else {
557        for (x, &y) in xys {
558            *x = limbs_xor_pos_neg_helper(*x ^ !y, &mut boundary_seen);
559        }
560    }
561    boundary_seen
562}
563
564// Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of one
565// `Integer` and the negative of another, writes the limbs of the bitwise xor of the `Integer`s to
566// the `Vec`. `xs` and `ys` may not be empty or only contain zeros.
567//
568// # Worst-case complexity
569// $T(n) = O(n)$
570//
571// $M(m) = O(m)$
572//
573// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
574// ys.len() - xs.len())`.
575//
576// # Panics
577// Panics if `xs` or `ys` are empty or contain only zeros.
578//
579// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op1` and the first
580// input is positive and the second is negative.
581pub_test! {limbs_xor_pos_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
582    let xs_len = xs.len();
583    let ys_len = ys.len();
584    let x_i = slice_leading_zeros(xs);
585    let y_i = slice_leading_zeros(ys);
586    assert!(x_i < xs_len);
587    assert!(y_i < ys_len);
588    if y_i >= xs_len {
589        xs[x_i].wrapping_neg_assign();
590        limbs_not_in_place(&mut xs[x_i + 1..]);
591        xs.extend(repeat_n(Limb::MAX, y_i - xs_len));
592        xs.push(ys[y_i] - 1);
593        xs.extend_from_slice(&ys[y_i + 1..]);
594        return;
595    } else if x_i >= ys_len {
596        xs[..ys_len].copy_from_slice(ys);
597        return;
598    }
599    let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i);
600    match xs_len.cmp(&ys_len) {
601        Less => {
602            if boundary_seen {
603                xs.extend_from_slice(&ys[xs_len..]);
604            } else {
605                for &y in &ys[xs_len..] {
606                    xs.push(limbs_xor_pos_neg_helper(!y, &mut boundary_seen));
607                }
608            }
609        }
610        Greater => {
611            if !boundary_seen {
612                for x in &mut xs[ys_len..] {
613                    *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen);
614                }
615            }
616        }
617        _ => {}
618    }
619    if slice_test_zero(xs) {
620        xs.push(1);
621    }
622}}
623
624fn limbs_xor_pos_neg_in_place_right_helper(
625    xs: &[Limb],
626    ys: &mut [Limb],
627    x_i: usize,
628    y_i: usize,
629) -> bool {
630    let max_i = max(x_i, y_i);
631    let mut boundary_seen = false;
632    match x_i.cmp(&y_i) {
633        Equal => {
634            ys[y_i] =
635                limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen);
636        }
637        Less => {
638            boundary_seen = true;
639            ys[x_i] = xs[x_i].wrapping_neg();
640            for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..y_i].iter()) {
641                *y = !x;
642            }
643            ys[y_i] -= 1;
644            ys[y_i] ^= xs[y_i];
645        }
646        Greater => {
647            boundary_seen = true;
648            ys[x_i] ^= xs[x_i];
649        }
650    }
651    let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter_mut());
652    if boundary_seen {
653        for (&x, y) in xys {
654            *y ^= x;
655        }
656    } else {
657        for (&x, y) in xys {
658            *y = limbs_xor_pos_neg_helper(x ^ !*y, &mut boundary_seen);
659        }
660    }
661    boundary_seen
662}
663
664// Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of one
665// `Integer` and the negative of another, writes the limbs of the bitwise xor of the `Integer`s to
666// the second (right) slice. `xs` and `ys` may not be empty or only contain zeros.
667//
668// # Worst-case complexity
669// $T(n) = O(n)$
670//
671// $M(m) = O(m)$
672//
673// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
674// ys.len() - xs.len())`.
675//
676// # Panics
677// Panics if `xs` or `ys` are empty or contain only zeros.
678//
679// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op2` and the first
680// input is positive and the second is negative.
681pub_test! {limbs_xor_pos_neg_in_place_right(xs: &[Limb], ys: &mut Vec<Limb>) {
682    let xs_len = xs.len();
683    let ys_len = ys.len();
684    let x_i = slice_leading_zeros(xs);
685    let y_i = slice_leading_zeros(ys);
686    assert!(x_i < xs_len);
687    assert!(y_i < ys_len);
688    if y_i >= xs_len {
689        ys[x_i] = xs[x_i].wrapping_neg();
690        for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) {
691            *y = !x;
692        }
693        for y in ys.iter_mut().take(y_i).skip(xs_len) {
694            *y = Limb::MAX;
695        }
696        ys[y_i] -= 1;
697        return;
698    } else if x_i >= ys_len {
699        ys.extend_from_slice(&xs[ys_len..]);
700        return;
701    }
702    let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i);
703    if xs_len > ys_len {
704        if boundary_seen {
705            ys.extend_from_slice(&xs[ys_len..]);
706        } else {
707            for &x in &xs[ys_len..] {
708                ys.push(limbs_xor_pos_neg_helper(!x, &mut boundary_seen));
709            }
710        }
711    } else if xs_len < ys_len && !boundary_seen {
712        for y in &mut ys[xs_len..] {
713            *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen);
714        }
715    }
716    if slice_test_zero(ys) {
717        ys.push(1);
718    }
719}}
720
721// Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of one `Integer` and the
722// negative of another, writes the limbs of the bitwise xor of the `Integer`s to the longer `Vec`
723// (or the first one, if they are equally long). `xs` and `ys` may not be empty or only contain
724// zeros. Returns a `bool` which is `false` when the output is to the first `Vec` and `true` when
725// it's to the second `Vec`.
726//
727// # Worst-case complexity
728// $T(n) = O(n)$
729//
730// $M(n) = O(1)$
731//
732// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
733//
734// # Panics
735// Panics if `xs` or `ys` are empty or contain only zeros.
736//
737// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where the first input is positive,
738// the second is negative, and the result is written to the longer input slice.
739pub_test! {limbs_xor_pos_neg_in_place_either(xs: &mut Vec<Limb>, ys: &mut Vec<Limb>) -> bool {
740    let xs_len = xs.len();
741    let ys_len = ys.len();
742    let x_i = slice_leading_zeros(xs);
743    let y_i = slice_leading_zeros(ys);
744    assert!(x_i < xs_len);
745    assert!(y_i < ys_len);
746    if y_i >= xs_len {
747        ys[x_i] = xs[x_i].wrapping_neg();
748        for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) {
749            *y = !x;
750        }
751        for y in &mut ys[xs_len..y_i] {
752            *y = Limb::MAX;
753        }
754        ys[y_i] -= 1;
755        return true;
756    } else if x_i >= ys_len {
757        xs[..ys_len].copy_from_slice(ys);
758        return false;
759    }
760    if xs_len >= ys_len {
761        let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i);
762        if xs_len != ys_len && !boundary_seen {
763            for x in &mut xs[ys_len..] {
764                *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen);
765            }
766        }
767        if slice_test_zero(xs) {
768            xs.push(1);
769        }
770        false
771    } else {
772        let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i);
773        if !boundary_seen {
774            for y in &mut ys[xs_len..] {
775                *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen);
776            }
777        }
778        if slice_test_zero(ys) {
779            ys.push(1);
780        }
781        true
782    }
783}}
784
785// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
786// `Integer`s, returns the limbs of the bitwise xor of the `Integer`s. `xs` and `ys` may not be
787// empty or only contain zeros.
788//
789// # Worst-case complexity
790// $T(n) = O(n)$
791//
792// $M(n) = O(n)$
793//
794// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
795//
796// # Panics
797// Panics if `xs` or `ys` are empty or contain only zeros.
798//
799// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res` is returned and both
800// inputs are negative.
801pub_test! {limbs_xor_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
802    let xs_len = xs.len();
803    let ys_len = ys.len();
804    let x_i = slice_leading_zeros(xs);
805    let y_i = slice_leading_zeros(ys);
806    assert!(x_i < xs_len);
807    assert!(y_i < ys_len);
808    if y_i >= xs_len {
809        let (result, borrow) = limbs_sub(ys, xs);
810        assert!(!borrow);
811        return result;
812    } else if x_i >= ys_len {
813        let (result, borrow) = limbs_sub(xs, ys);
814        assert!(!borrow);
815        return result;
816    }
817    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
818    let mut out = vec![0; min_i];
819    if x_i == y_i {
820        out.push(xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg());
821    } else {
822        let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) };
823        out.push(min_zs[min_i].wrapping_neg());
824        out.extend(min_zs[min_i + 1..max_i].iter().map(|z| !z));
825        out.push((max_zs[max_i] - 1) ^ min_zs[max_i]);
826    }
827    out.extend(
828        xs[max_i + 1..]
829            .iter()
830            .zip(ys[max_i + 1..].iter())
831            .map(|(x, y)| x ^ y),
832    );
833    match xs_len.cmp(&ys_len) {
834        Less => out.extend_from_slice(&ys[xs_len..]),
835        Greater => out.extend_from_slice(&xs[ys_len..]),
836        _ => {}
837    }
838    out
839}}
840
841// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
842// `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise xor of the `Integer`s to
843// an output slice. `xs` and `ys` may not be empty or only contain zeros. The output slice must be
844// at least as long as the longer input slice.
845//
846// # Worst-case complexity
847// $T(n) = O(n)$
848//
849// $M(n) = O(1)$
850//
851// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
852//
853// # Panics
854// Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of
855// `xs` and `ys`.
856//
857// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are negative.
858pub_test! {limbs_xor_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
859    let xs_len = xs.len();
860    let ys_len = ys.len();
861    assert!(out.len() >= xs_len);
862    assert!(out.len() >= ys_len);
863    let x_i = slice_leading_zeros(xs);
864    let y_i = slice_leading_zeros(ys);
865    assert!(x_i < xs_len);
866    assert!(y_i < ys_len);
867    if y_i >= xs_len {
868        assert!(!limbs_sub_greater_to_out(out, ys, xs));
869        return;
870    } else if x_i >= ys_len {
871        assert!(!limbs_sub_greater_to_out(out, xs, ys));
872        return;
873    }
874    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
875    slice_set_zero(&mut out[..min_i]);
876    if x_i == y_i {
877        out[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg();
878    } else {
879        let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) };
880        out[min_i] = min_zs[min_i].wrapping_neg();
881        for (out, &z) in out[min_i + 1..max_i]
882            .iter_mut()
883            .zip(min_zs[min_i + 1..max_i].iter())
884        {
885            *out = !z;
886        }
887        out[max_i] = (max_zs[max_i] - 1) ^ min_zs[max_i];
888    }
889    for (out, (&x, &y)) in out[max_i + 1..]
890        .iter_mut()
891        .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()))
892    {
893        *out = x ^ y;
894    }
895    match xs_len.cmp(&ys_len) {
896        Less => out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]),
897        Greater => out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]),
898        _ => {}
899    }
900}}
901
902fn limbs_xor_neg_neg_in_place_helper(xs: &mut [Limb], ys: &[Limb], x_i: usize, y_i: usize) {
903    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
904    if x_i == y_i {
905        xs[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg();
906    } else if x_i <= y_i {
907        xs[min_i].wrapping_neg_assign();
908        limbs_not_in_place(&mut xs[min_i + 1..max_i]);
909        xs[max_i] ^= ys[max_i] - 1;
910    } else {
911        xs[min_i] = ys[min_i].wrapping_neg();
912        for (x, &y) in xs[min_i + 1..max_i].iter_mut().zip(ys[min_i + 1..].iter()) {
913            *x = !y;
914        }
915        xs[max_i] -= 1;
916        xs[max_i] ^= ys[max_i];
917    }
918    for (x, &y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
919        *x ^= y;
920    }
921}
922
923// Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of the
924// negatives of two `Integer`s, writes the limbs of the bitwise xor of the `Integer`s to the `Vec`.
925// `xs` and `ys` may not be empty or only contain zeros.
926//
927// # Worst-case complexity
928// $T(n) = O(n)$
929//
930// $M(m) = O(m)$
931//
932// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
933// ys.len() - xs.len())`.
934//
935// # Panics
936// Panics if `xs` or `ys` are empty or contain only zeros.
937//
938// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op1` and both inputs
939// are negative.
940pub_test! {limbs_xor_neg_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
941    let xs_len = xs.len();
942    let ys_len = ys.len();
943    let x_i = slice_leading_zeros(xs);
944    let y_i = slice_leading_zeros(ys);
945    assert!(x_i < xs_len);
946    assert!(y_i < ys_len);
947    if y_i >= xs_len {
948        assert!(!limbs_vec_sub_in_place_right(ys, xs));
949    } else if x_i >= ys_len {
950        assert!(!limbs_sub_greater_in_place_left(xs, ys));
951    } else {
952        limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i);
953        if xs_len < ys_len {
954            xs.extend_from_slice(&ys[xs_len..]);
955        }
956    }
957}}
958
959// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
960// `Integer`s, writes the limbs of the bitwise xor of the `Integer`s to the longer slice (or the
961// first one, if they are equally long). `xs` and `ys` may not be empty or only contain zeros.
962// Returns `false` when the output is to the first slice and `true` when it's to the second slice.
963//
964// # Worst-case complexity
965// $T(n) = O(n)$
966//
967// $M(n) = O(1)$
968//
969// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
970//
971// # Panics
972// Panics if `xs` or `ys` are empty or contain only zeros.
973//
974// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are negative and
975// the result is written to the longer input slice.
976pub_test! {limbs_xor_neg_neg_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool {
977    let xs_len = xs.len();
978    let ys_len = ys.len();
979    let x_i = slice_leading_zeros(xs);
980    let y_i = slice_leading_zeros(ys);
981    assert!(x_i < xs_len);
982    assert!(y_i < ys_len);
983    if y_i >= xs_len {
984        assert!(!limbs_sub_greater_in_place_left(ys, xs));
985        true
986    } else if x_i >= ys_len {
987        assert!(!limbs_sub_greater_in_place_left(xs, ys));
988        false
989    } else if xs_len >= ys_len {
990        limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i);
991        false
992    } else {
993        limbs_xor_neg_neg_in_place_helper(ys, xs, y_i, x_i);
994        true
995    }
996}}
997
998impl Natural {
999    fn xor_assign_neg_limb_pos(&mut self, other: Limb) {
1000        match self {
1001            &mut Natural::ZERO => {}
1002            Natural(Small(small)) => {
1003                let result = small.wrapping_neg() ^ other;
1004                if result == 0 {
1005                    *self = Natural(Large(vec![0, 1]));
1006                } else {
1007                    *small = result.wrapping_neg();
1008                }
1009            }
1010            Natural(Large(limbs)) => {
1011                limbs_vec_neg_xor_limb_in_place(limbs, other);
1012                self.trim();
1013            }
1014        }
1015    }
1016
1017    fn xor_neg_limb_pos(&self, other: Limb) -> Natural {
1018        match self {
1019            &Natural::ZERO => self.clone(),
1020            Natural(Small(small)) => {
1021                let result = small.wrapping_neg() ^ other;
1022                Natural(if result == 0 {
1023                    Large(vec![0, 1])
1024                } else {
1025                    Small(result.wrapping_neg())
1026                })
1027            }
1028            Natural(Large(limbs)) => {
1029                Natural::from_owned_limbs_asc(limbs_neg_xor_limb(limbs, other))
1030            }
1031        }
1032    }
1033
1034    fn xor_assign_pos_limb_neg(&mut self, other: Limb) {
1035        match self {
1036            Natural(Small(small)) => {
1037                let result = *small ^ other;
1038                if result == 0 {
1039                    *self = Natural(Large(vec![0, 1]));
1040                } else {
1041                    *small = result.wrapping_neg();
1042                }
1043            }
1044            Natural(Large(limbs)) => {
1045                limbs_vec_pos_xor_limb_neg_in_place(limbs, other);
1046                self.trim();
1047            }
1048        }
1049    }
1050
1051    fn xor_pos_limb_neg(&self, other: Limb) -> Natural {
1052        Natural(match self {
1053            Natural(Small(small)) => {
1054                let result = small ^ other;
1055                if result == 0 {
1056                    Large(vec![0, 1])
1057                } else {
1058                    Small(result.wrapping_neg())
1059                }
1060            }
1061            Natural(Large(limbs)) => Large(limbs_pos_xor_limb_neg(limbs, other)),
1062        })
1063    }
1064
1065    fn xor_assign_neg_limb_neg(&mut self, other: Limb) {
1066        match &mut *self {
1067            Natural(Small(small)) => *small = small.wrapping_neg() ^ other,
1068            Natural(Large(limbs)) => {
1069                limbs_neg_xor_limb_neg_in_place(limbs, other);
1070                self.trim();
1071            }
1072        }
1073    }
1074
1075    fn xor_neg_limb_neg(&self, other: Limb) -> Natural {
1076        match self {
1077            Natural(Small(small)) => Natural(Small(small.wrapping_neg() ^ other)),
1078            Natural(Large(limbs)) => {
1079                Natural::from_owned_limbs_asc(limbs_neg_xor_limb_neg(limbs, other))
1080            }
1081        }
1082    }
1083
1084    fn xor_assign_pos_neg(&mut self, mut other: Natural) {
1085        match (&mut *self, &mut other) {
1086            (Natural(Small(x)), _) => {
1087                other.xor_assign_neg_limb_pos(*x);
1088                *self = other;
1089            }
1090            (_, Natural(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()),
1091            (Natural(Large(xs)), Natural(Large(ys))) => {
1092                if limbs_xor_pos_neg_in_place_either(xs, ys) {
1093                    *self = other;
1094                }
1095                self.trim();
1096            }
1097        }
1098    }
1099
1100    fn xor_assign_pos_neg_ref(&mut self, other: &Natural) {
1101        match (&mut *self, other) {
1102            (Natural(Small(x)), _) => *self = other.xor_neg_limb_pos(*x),
1103            (_, Natural(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()),
1104            (Natural(Large(xs)), Natural(Large(ys))) => {
1105                limbs_xor_pos_neg_in_place_left(xs, ys);
1106                self.trim();
1107            }
1108        }
1109    }
1110
1111    fn xor_assign_neg_pos(&mut self, mut other: Natural) {
1112        other.xor_assign_pos_neg_ref(&*self);
1113        *self = other;
1114    }
1115
1116    fn xor_assign_neg_pos_ref(&mut self, other: &Natural) {
1117        match (&mut *self, other) {
1118            (Natural(Small(x)), _) => *self = other.xor_pos_limb_neg(x.wrapping_neg()),
1119            (_, Natural(Small(y))) => self.xor_assign_neg_limb_pos(*y),
1120            (Natural(Large(xs)), Natural(Large(ys))) => {
1121                limbs_xor_pos_neg_in_place_right(ys, xs);
1122                self.trim();
1123            }
1124        }
1125    }
1126
1127    fn xor_pos_neg(&self, other: &Natural) -> Natural {
1128        match (self, other) {
1129            (&Natural(Small(x)), _) => other.xor_neg_limb_pos(x),
1130            (_, &Natural(Small(y))) => self.xor_pos_limb_neg(y.wrapping_neg()),
1131            (Natural(Large(xs)), Natural(Large(ys))) => {
1132                Natural::from_owned_limbs_asc(limbs_xor_pos_neg(xs, ys))
1133            }
1134        }
1135    }
1136
1137    fn xor_assign_neg_neg(&mut self, mut other: Natural) {
1138        match (&mut *self, &mut other) {
1139            (Natural(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()),
1140            (_, Natural(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()),
1141            (Natural(Large(xs)), Natural(Large(ys))) => {
1142                if limbs_xor_neg_neg_in_place_either(xs, ys) {
1143                    *self = other;
1144                }
1145                self.trim();
1146            }
1147        }
1148    }
1149
1150    fn xor_assign_neg_neg_ref(&mut self, other: &Natural) {
1151        match (&mut *self, other) {
1152            (Natural(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()),
1153            (_, Natural(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()),
1154            (Natural(Large(xs)), Natural(Large(ys))) => {
1155                limbs_xor_neg_neg_in_place_left(xs, ys);
1156                self.trim();
1157            }
1158        }
1159    }
1160
1161    fn xor_neg_neg(&self, other: &Natural) -> Natural {
1162        match (self, other) {
1163            (&Natural(Small(x)), _) => other.xor_neg_limb_neg(x.wrapping_neg()),
1164            (_, &Natural(Small(y))) => self.xor_neg_limb_neg(y.wrapping_neg()),
1165            (Natural(Large(xs)), Natural(Large(ys))) => {
1166                Natural::from_owned_limbs_asc(limbs_xor_neg_neg(xs, ys))
1167            }
1168        }
1169    }
1170}
1171
1172impl BitXor<Integer> for Integer {
1173    type Output = Integer;
1174
1175    /// Takes the bitwise xor of two [`Integer`]s, taking both by value.
1176    ///
1177    /// $$
1178    /// f(x, y) = x \oplus y.
1179    /// $$
1180    ///
1181    /// # Worst-case complexity
1182    /// $T(n) = O(n)$
1183    ///
1184    /// $M(n) = O(1)$
1185    ///
1186    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1187    /// other.significant_bits())`.
1188    ///
1189    /// # Examples
1190    /// ```
1191    /// use malachite_base::num::arithmetic::traits::Pow;
1192    /// use malachite_base::num::basic::traits::One;
1193    /// use malachite_nz::integer::Integer;
1194    ///
1195    /// assert_eq!(Integer::from(-123) ^ Integer::from(-456), 445);
1196    /// assert_eq!(
1197    ///     -Integer::from(10u32).pow(12) ^ -(Integer::from(10u32).pow(12) + Integer::ONE),
1198    ///     8191
1199    /// );
1200    /// ```
1201    #[inline]
1202    fn bitxor(mut self, other: Integer) -> Integer {
1203        self ^= other;
1204        self
1205    }
1206}
1207
1208impl BitXor<&Integer> for Integer {
1209    type Output = Integer;
1210
1211    /// Takes the bitwise xor of two [`Integer`]s, taking the first by value and the second by
1212    /// reference.
1213    ///
1214    /// $$
1215    /// f(x, y) = x \oplus y.
1216    /// $$
1217    ///
1218    /// # Worst-case complexity
1219    /// $T(n) = O(n)$
1220    ///
1221    /// $M(m) = O(m)$
1222    ///
1223    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1224    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1225    ///
1226    /// # Examples
1227    /// ```
1228    /// use malachite_base::num::arithmetic::traits::Pow;
1229    /// use malachite_base::num::basic::traits::One;
1230    /// use malachite_nz::integer::Integer;
1231    ///
1232    /// assert_eq!(Integer::from(-123) ^ &Integer::from(-456), 445);
1233    /// assert_eq!(
1234    ///     -Integer::from(10u32).pow(12) ^ &-(Integer::from(10u32).pow(12) + Integer::ONE),
1235    ///     8191
1236    /// );
1237    /// ```
1238    #[inline]
1239    fn bitxor(mut self, other: &Integer) -> Integer {
1240        self ^= other;
1241        self
1242    }
1243}
1244
1245impl BitXor<Integer> for &Integer {
1246    type Output = Integer;
1247
1248    /// Takes the bitwise xor of two [`Integer`]s, taking the first by reference and the second by
1249    /// value.
1250    ///
1251    /// $$
1252    /// f(x, y) = x \oplus y.
1253    /// $$
1254    ///
1255    /// # Worst-case complexity
1256    /// $T(n) = O(n)$
1257    ///
1258    /// $M(m) = O(m)$
1259    ///
1260    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1261    /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
1262    ///
1263    /// # Examples
1264    /// ```
1265    /// use malachite_base::num::arithmetic::traits::Pow;
1266    /// use malachite_base::num::basic::traits::One;
1267    /// use malachite_nz::integer::Integer;
1268    ///
1269    /// assert_eq!(&Integer::from(-123) ^ Integer::from(-456), 445);
1270    /// assert_eq!(
1271    ///     &-Integer::from(10u32).pow(12) ^ -(Integer::from(10u32).pow(12) + Integer::ONE),
1272    ///     8191
1273    /// );
1274    /// ```
1275    #[inline]
1276    fn bitxor(self, mut other: Integer) -> Integer {
1277        other ^= self;
1278        other
1279    }
1280}
1281
1282impl BitXor<&Integer> for &Integer {
1283    type Output = Integer;
1284
1285    /// Takes the bitwise xor of two [`Integer`]s, taking both by reference.
1286    ///
1287    /// $$
1288    /// f(x, y) = x \oplus y.
1289    /// $$
1290    ///
1291    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1292    /// other.significant_bits())`.
1293    ///
1294    /// # Examples
1295    /// ```
1296    /// use malachite_base::num::arithmetic::traits::Pow;
1297    /// use malachite_base::num::basic::traits::One;
1298    /// use malachite_nz::integer::Integer;
1299    ///
1300    /// assert_eq!(&Integer::from(-123) ^ &Integer::from(-456), 445);
1301    /// assert_eq!(
1302    ///     &-Integer::from(10u32).pow(12) ^ &-(Integer::from(10u32).pow(12) + Integer::ONE),
1303    ///     8191
1304    /// );
1305    /// ```
1306    fn bitxor(self, other: &Integer) -> Integer {
1307        match (self.sign, other.sign) {
1308            (true, true) => Integer {
1309                sign: true,
1310                abs: &self.abs ^ &other.abs,
1311            },
1312            (true, false) => Integer {
1313                sign: false,
1314                abs: self.abs.xor_pos_neg(&other.abs),
1315            },
1316            (false, true) => Integer {
1317                sign: false,
1318                abs: other.abs.xor_pos_neg(&self.abs),
1319            },
1320            (false, false) => Integer {
1321                sign: true,
1322                abs: self.abs.xor_neg_neg(&other.abs),
1323            },
1324        }
1325    }
1326}
1327
1328impl BitXorAssign<Integer> for Integer {
1329    /// Bitwise-xors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1330    /// right-hand side by value.
1331    ///
1332    /// $$
1333    /// x \gets x \oplus y.
1334    /// $$
1335    ///
1336    /// # Worst-case complexity
1337    /// $T(n) = O(n)$
1338    ///
1339    /// $M(n) = O(1)$
1340    ///
1341    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1342    /// other.significant_bits())`.
1343    ///
1344    /// # Examples
1345    /// ```
1346    /// use malachite_nz::integer::Integer;
1347    ///
1348    /// let mut x = Integer::from(u32::MAX);
1349    /// x ^= Integer::from(0x0000000f);
1350    /// x ^= Integer::from(0x00000f00);
1351    /// x ^= Integer::from(0x000f_0000);
1352    /// x ^= Integer::from(0x0f000000);
1353    /// assert_eq!(x, 0xf0f0_f0f0u32);
1354    /// ```
1355    fn bitxor_assign(&mut self, other: Integer) {
1356        match (self.sign, other.sign) {
1357            (true, true) => self.abs.bitxor_assign(other.abs),
1358            (true, false) => {
1359                self.sign = false;
1360                self.abs.xor_assign_pos_neg(other.abs);
1361            }
1362            (false, true) => self.abs.xor_assign_neg_pos(other.abs),
1363            (false, false) => {
1364                self.sign = true;
1365                self.abs.xor_assign_neg_neg(other.abs);
1366            }
1367        }
1368    }
1369}
1370
1371impl BitXorAssign<&Integer> for Integer {
1372    /// Bitwise-xors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1373    /// right-hand side by reference.
1374    ///
1375    /// $$
1376    /// x \gets x \oplus y.
1377    /// $$
1378    ///
1379    /// # Worst-case complexity
1380    /// $T(n) = O(n)$
1381    ///
1382    /// $M(m) = O(m)$
1383    ///
1384    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1385    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1386    ///
1387    /// # Examples
1388    /// ```
1389    /// use malachite_nz::integer::Integer;
1390    ///
1391    /// let mut x = Integer::from(u32::MAX);
1392    /// x ^= &Integer::from(0x0000000f);
1393    /// x ^= &Integer::from(0x00000f00);
1394    /// x ^= &Integer::from(0x000f_0000);
1395    /// x ^= &Integer::from(0x0f000000);
1396    /// assert_eq!(x, 0xf0f0_f0f0u32);
1397    /// ```
1398    fn bitxor_assign(&mut self, other: &Integer) {
1399        match (self.sign, other.sign) {
1400            (true, true) => self.abs.bitxor_assign(&other.abs),
1401            (true, false) => {
1402                self.sign = false;
1403                self.abs.xor_assign_pos_neg_ref(&other.abs);
1404            }
1405            (false, true) => self.abs.xor_assign_neg_pos_ref(&other.abs),
1406            (false, false) => {
1407                self.sign = true;
1408                self.abs.xor_assign_neg_neg_ref(&other.abs);
1409            }
1410        }
1411    }
1412}