Skip to main content

malachite_nz/integer/logic/
xor.rs

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