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::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 if !boundary_seen => {
611                for x in &mut xs[ys_len..] {
612                    *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen);
613                }
614            }
615        _ => {}
616    }
617    if slice_test_zero(xs) {
618        xs.push(1);
619    }
620}}
621
622fn limbs_xor_pos_neg_in_place_right_helper(
623    xs: &[Limb],
624    ys: &mut [Limb],
625    x_i: usize,
626    y_i: usize,
627) -> bool {
628    let max_i = max(x_i, y_i);
629    let mut boundary_seen = false;
630    match x_i.cmp(&y_i) {
631        Equal => {
632            ys[y_i] =
633                limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen);
634        }
635        Less => {
636            boundary_seen = true;
637            ys[x_i] = xs[x_i].wrapping_neg();
638            for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..y_i].iter()) {
639                *y = !x;
640            }
641            ys[y_i] -= 1;
642            ys[y_i] ^= xs[y_i];
643        }
644        Greater => {
645            boundary_seen = true;
646            ys[x_i] ^= xs[x_i];
647        }
648    }
649    let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter_mut());
650    if boundary_seen {
651        for (&x, y) in xys {
652            *y ^= x;
653        }
654    } else {
655        for (&x, y) in xys {
656            *y = limbs_xor_pos_neg_helper(x ^ !*y, &mut boundary_seen);
657        }
658    }
659    boundary_seen
660}
661
662// Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of one
663// `Integer` and the negative of another, writes the limbs of the bitwise xor of the `Integer`s to
664// the second (right) slice. `xs` and `ys` may not be empty or only contain zeros.
665//
666// # Worst-case complexity
667// $T(n) = O(n)$
668//
669// $M(m) = O(m)$
670//
671// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
672// ys.len() - xs.len())`.
673//
674// # Panics
675// Panics if `xs` or `ys` are empty or contain only zeros.
676//
677// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op2` and the first
678// input is positive and the second is negative.
679pub_test! {limbs_xor_pos_neg_in_place_right(xs: &[Limb], ys: &mut Vec<Limb>) {
680    let xs_len = xs.len();
681    let ys_len = ys.len();
682    let x_i = slice_leading_zeros(xs);
683    let y_i = slice_leading_zeros(ys);
684    assert!(x_i < xs_len);
685    assert!(y_i < ys_len);
686    if y_i >= xs_len {
687        ys[x_i] = xs[x_i].wrapping_neg();
688        for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) {
689            *y = !x;
690        }
691        for y in ys.iter_mut().take(y_i).skip(xs_len) {
692            *y = Limb::MAX;
693        }
694        ys[y_i] -= 1;
695        return;
696    } else if x_i >= ys_len {
697        ys.extend_from_slice(&xs[ys_len..]);
698        return;
699    }
700    let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i);
701    if xs_len > ys_len {
702        if boundary_seen {
703            ys.extend_from_slice(&xs[ys_len..]);
704        } else {
705            for &x in &xs[ys_len..] {
706                ys.push(limbs_xor_pos_neg_helper(!x, &mut boundary_seen));
707            }
708        }
709    } else if xs_len < ys_len && !boundary_seen {
710        for y in &mut ys[xs_len..] {
711            *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen);
712        }
713    }
714    if slice_test_zero(ys) {
715        ys.push(1);
716    }
717}}
718
719// Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of one `Integer` and the
720// negative of another, writes the limbs of the bitwise xor of the `Integer`s to the longer `Vec`
721// (or the first one, if they are equally long). `xs` and `ys` may not be empty or only contain
722// zeros. Returns a `bool` which is `false` when the output is to the first `Vec` and `true` when
723// it's to the second `Vec`.
724//
725// # Worst-case complexity
726// $T(n) = O(n)$
727//
728// $M(n) = O(1)$
729//
730// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
731//
732// # Panics
733// Panics if `xs` or `ys` are empty or contain only zeros.
734//
735// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where the first input is positive,
736// the second is negative, and the result is written to the longer input slice.
737pub_test! {limbs_xor_pos_neg_in_place_either(xs: &mut Vec<Limb>, ys: &mut Vec<Limb>) -> bool {
738    let xs_len = xs.len();
739    let ys_len = ys.len();
740    let x_i = slice_leading_zeros(xs);
741    let y_i = slice_leading_zeros(ys);
742    assert!(x_i < xs_len);
743    assert!(y_i < ys_len);
744    if y_i >= xs_len {
745        ys[x_i] = xs[x_i].wrapping_neg();
746        for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) {
747            *y = !x;
748        }
749        for y in &mut ys[xs_len..y_i] {
750            *y = Limb::MAX;
751        }
752        ys[y_i] -= 1;
753        return true;
754    } else if x_i >= ys_len {
755        xs[..ys_len].copy_from_slice(ys);
756        return false;
757    }
758    if xs_len >= ys_len {
759        let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i);
760        if xs_len != ys_len && !boundary_seen {
761            for x in &mut xs[ys_len..] {
762                *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen);
763            }
764        }
765        if slice_test_zero(xs) {
766            xs.push(1);
767        }
768        false
769    } else {
770        let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i);
771        if !boundary_seen {
772            for y in &mut ys[xs_len..] {
773                *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen);
774            }
775        }
776        if slice_test_zero(ys) {
777            ys.push(1);
778        }
779        true
780    }
781}}
782
783// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
784// `Integer`s, returns the limbs of the bitwise xor of the `Integer`s. `xs` and `ys` may not be
785// empty or only contain zeros.
786//
787// # Worst-case complexity
788// $T(n) = O(n)$
789//
790// $M(n) = O(n)$
791//
792// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
793//
794// # Panics
795// Panics if `xs` or `ys` are empty or contain only zeros.
796//
797// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res` is returned and both
798// inputs are negative.
799pub_test! {limbs_xor_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
800    let xs_len = xs.len();
801    let ys_len = ys.len();
802    let x_i = slice_leading_zeros(xs);
803    let y_i = slice_leading_zeros(ys);
804    assert!(x_i < xs_len);
805    assert!(y_i < ys_len);
806    if y_i >= xs_len {
807        let (result, borrow) = limbs_sub(ys, xs);
808        assert!(!borrow);
809        return result;
810    } else if x_i >= ys_len {
811        let (result, borrow) = limbs_sub(xs, ys);
812        assert!(!borrow);
813        return result;
814    }
815    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
816    let mut out = vec![0; min_i];
817    if x_i == y_i {
818        out.push(xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg());
819    } else {
820        let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) };
821        out.push(min_zs[min_i].wrapping_neg());
822        out.extend(min_zs[min_i + 1..max_i].iter().map(|z| !z));
823        out.push((max_zs[max_i] - 1) ^ min_zs[max_i]);
824    }
825    out.extend(
826        xs[max_i + 1..]
827            .iter()
828            .zip(ys[max_i + 1..].iter())
829            .map(|(x, y)| x ^ y),
830    );
831    match xs_len.cmp(&ys_len) {
832        Less => out.extend_from_slice(&ys[xs_len..]),
833        Greater => out.extend_from_slice(&xs[ys_len..]),
834        _ => {}
835    }
836    out
837}}
838
839// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
840// `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise xor of the `Integer`s to
841// an output slice. `xs` and `ys` may not be empty or only contain zeros. The output slice must be
842// at least as long as the longer input slice.
843//
844// # Worst-case complexity
845// $T(n) = O(n)$
846//
847// $M(n) = O(1)$
848//
849// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
850//
851// # Panics
852// Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of
853// `xs` and `ys`.
854//
855// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are negative.
856pub_test! {limbs_xor_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
857    let xs_len = xs.len();
858    let ys_len = ys.len();
859    assert!(out.len() >= xs_len);
860    assert!(out.len() >= ys_len);
861    let x_i = slice_leading_zeros(xs);
862    let y_i = slice_leading_zeros(ys);
863    assert!(x_i < xs_len);
864    assert!(y_i < ys_len);
865    if y_i >= xs_len {
866        assert!(!limbs_sub_greater_to_out(out, ys, xs));
867        return;
868    } else if x_i >= ys_len {
869        assert!(!limbs_sub_greater_to_out(out, xs, ys));
870        return;
871    }
872    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
873    slice_set_zero(&mut out[..min_i]);
874    if x_i == y_i {
875        out[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg();
876    } else {
877        let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) };
878        out[min_i] = min_zs[min_i].wrapping_neg();
879        for (out, &z) in out[min_i + 1..max_i]
880            .iter_mut()
881            .zip(min_zs[min_i + 1..max_i].iter())
882        {
883            *out = !z;
884        }
885        out[max_i] = (max_zs[max_i] - 1) ^ min_zs[max_i];
886    }
887    for (out, (&x, &y)) in out[max_i + 1..]
888        .iter_mut()
889        .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()))
890    {
891        *out = x ^ y;
892    }
893    match xs_len.cmp(&ys_len) {
894        Less => out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]),
895        Greater => out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]),
896        _ => {}
897    }
898}}
899
900fn limbs_xor_neg_neg_in_place_helper(xs: &mut [Limb], ys: &[Limb], x_i: usize, y_i: usize) {
901    let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
902    if x_i == y_i {
903        xs[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg();
904    } else if x_i <= y_i {
905        xs[min_i].wrapping_neg_assign();
906        limbs_not_in_place(&mut xs[min_i + 1..max_i]);
907        xs[max_i] ^= ys[max_i] - 1;
908    } else {
909        xs[min_i] = ys[min_i].wrapping_neg();
910        for (x, &y) in xs[min_i + 1..max_i].iter_mut().zip(ys[min_i + 1..].iter()) {
911            *x = !y;
912        }
913        xs[max_i] -= 1;
914        xs[max_i] ^= ys[max_i];
915    }
916    for (x, &y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
917        *x ^= y;
918    }
919}
920
921// Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of the
922// negatives of two `Integer`s, writes the limbs of the bitwise xor of the `Integer`s to the `Vec`.
923// `xs` and `ys` may not be empty or only contain zeros.
924//
925// # Worst-case complexity
926// $T(n) = O(n)$
927//
928// $M(m) = O(m)$
929//
930// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
931// ys.len() - xs.len())`.
932//
933// # Panics
934// Panics if `xs` or `ys` are empty or contain only zeros.
935//
936// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op1` and both inputs
937// are negative.
938pub_test! {limbs_xor_neg_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
939    let xs_len = xs.len();
940    let ys_len = ys.len();
941    let x_i = slice_leading_zeros(xs);
942    let y_i = slice_leading_zeros(ys);
943    assert!(x_i < xs_len);
944    assert!(y_i < ys_len);
945    if y_i >= xs_len {
946        assert!(!limbs_vec_sub_in_place_right(ys, xs));
947    } else if x_i >= ys_len {
948        assert!(!limbs_sub_greater_in_place_left(xs, ys));
949    } else {
950        limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i);
951        if xs_len < ys_len {
952            xs.extend_from_slice(&ys[xs_len..]);
953        }
954    }
955}}
956
957// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
958// `Integer`s, writes the limbs of the bitwise xor of the `Integer`s to the longer slice (or the
959// first one, if they are equally long). `xs` and `ys` may not be empty or only contain zeros.
960// Returns `false` when the output is to the first slice and `true` when it's to the second slice.
961//
962// # Worst-case complexity
963// $T(n) = O(n)$
964//
965// $M(n) = O(1)$
966//
967// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
968//
969// # Panics
970// Panics if `xs` or `ys` are empty or contain only zeros.
971//
972// This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are negative and
973// the result is written to the longer input slice.
974pub_test! {limbs_xor_neg_neg_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool {
975    let xs_len = xs.len();
976    let ys_len = ys.len();
977    let x_i = slice_leading_zeros(xs);
978    let y_i = slice_leading_zeros(ys);
979    assert!(x_i < xs_len);
980    assert!(y_i < ys_len);
981    if y_i >= xs_len {
982        assert!(!limbs_sub_greater_in_place_left(ys, xs));
983        true
984    } else if x_i >= ys_len {
985        assert!(!limbs_sub_greater_in_place_left(xs, ys));
986        false
987    } else if xs_len >= ys_len {
988        limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i);
989        false
990    } else {
991        limbs_xor_neg_neg_in_place_helper(ys, xs, y_i, x_i);
992        true
993    }
994}}
995
996impl Natural {
997    fn xor_assign_neg_limb_pos(&mut self, other: Limb) {
998        match self {
999            &mut Self::ZERO => {}
1000            Self(Small(small)) => {
1001                let result = small.wrapping_neg() ^ other;
1002                if result == 0 {
1003                    *self = Self(Large(vec![0, 1]));
1004                } else {
1005                    *small = result.wrapping_neg();
1006                }
1007            }
1008            Self(Large(limbs)) => {
1009                limbs_vec_neg_xor_limb_in_place(limbs, other);
1010                self.trim();
1011            }
1012        }
1013    }
1014
1015    fn xor_neg_limb_pos(&self, other: Limb) -> Self {
1016        match self {
1017            &Self::ZERO => self.clone(),
1018            Self(Small(small)) => {
1019                let result = small.wrapping_neg() ^ other;
1020                Self(if result == 0 {
1021                    Large(vec![0, 1])
1022                } else {
1023                    Small(result.wrapping_neg())
1024                })
1025            }
1026            Self(Large(limbs)) => Self::from_owned_limbs_asc(limbs_neg_xor_limb(limbs, other)),
1027        }
1028    }
1029
1030    fn xor_assign_pos_limb_neg(&mut self, other: Limb) {
1031        match self {
1032            Self(Small(small)) => {
1033                let result = *small ^ other;
1034                if result == 0 {
1035                    *self = Self(Large(vec![0, 1]));
1036                } else {
1037                    *small = result.wrapping_neg();
1038                }
1039            }
1040            Self(Large(limbs)) => {
1041                limbs_vec_pos_xor_limb_neg_in_place(limbs, other);
1042                self.trim();
1043            }
1044        }
1045    }
1046
1047    fn xor_pos_limb_neg(&self, other: Limb) -> Self {
1048        Self(match self {
1049            Self(Small(small)) => {
1050                let result = small ^ other;
1051                if result == 0 {
1052                    Large(vec![0, 1])
1053                } else {
1054                    Small(result.wrapping_neg())
1055                }
1056            }
1057            Self(Large(limbs)) => Large(limbs_pos_xor_limb_neg(limbs, other)),
1058        })
1059    }
1060
1061    fn xor_assign_neg_limb_neg(&mut self, other: Limb) {
1062        match &mut *self {
1063            Self(Small(small)) => *small = small.wrapping_neg() ^ other,
1064            Self(Large(limbs)) => {
1065                limbs_neg_xor_limb_neg_in_place(limbs, other);
1066                self.trim();
1067            }
1068        }
1069    }
1070
1071    fn xor_neg_limb_neg(&self, other: Limb) -> Self {
1072        match self {
1073            Self(Small(small)) => Self(Small(small.wrapping_neg() ^ other)),
1074            Self(Large(limbs)) => Self::from_owned_limbs_asc(limbs_neg_xor_limb_neg(limbs, other)),
1075        }
1076    }
1077
1078    fn xor_assign_pos_neg(&mut self, mut other: Self) {
1079        match (&mut *self, &mut other) {
1080            (Self(Small(x)), _) => {
1081                other.xor_assign_neg_limb_pos(*x);
1082                *self = other;
1083            }
1084            (_, Self(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()),
1085            (Self(Large(xs)), Self(Large(ys))) => {
1086                if limbs_xor_pos_neg_in_place_either(xs, ys) {
1087                    *self = other;
1088                }
1089                self.trim();
1090            }
1091        }
1092    }
1093
1094    fn xor_assign_pos_neg_ref(&mut self, other: &Self) {
1095        match (&mut *self, other) {
1096            (Self(Small(x)), _) => *self = other.xor_neg_limb_pos(*x),
1097            (_, Self(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()),
1098            (Self(Large(xs)), Self(Large(ys))) => {
1099                limbs_xor_pos_neg_in_place_left(xs, ys);
1100                self.trim();
1101            }
1102        }
1103    }
1104
1105    fn xor_assign_neg_pos(&mut self, mut other: Self) {
1106        other.xor_assign_pos_neg_ref(&*self);
1107        *self = other;
1108    }
1109
1110    fn xor_assign_neg_pos_ref(&mut self, other: &Self) {
1111        match (&mut *self, other) {
1112            (Self(Small(x)), _) => *self = other.xor_pos_limb_neg(x.wrapping_neg()),
1113            (_, Self(Small(y))) => self.xor_assign_neg_limb_pos(*y),
1114            (Self(Large(xs)), Self(Large(ys))) => {
1115                limbs_xor_pos_neg_in_place_right(ys, xs);
1116                self.trim();
1117            }
1118        }
1119    }
1120
1121    fn xor_pos_neg(&self, other: &Self) -> Self {
1122        match (self, other) {
1123            (&Self(Small(x)), _) => other.xor_neg_limb_pos(x),
1124            (_, &Self(Small(y))) => self.xor_pos_limb_neg(y.wrapping_neg()),
1125            (Self(Large(xs)), Self(Large(ys))) => {
1126                Self::from_owned_limbs_asc(limbs_xor_pos_neg(xs, ys))
1127            }
1128        }
1129    }
1130
1131    fn xor_assign_neg_neg(&mut self, mut other: Self) {
1132        match (&mut *self, &mut other) {
1133            (Self(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()),
1134            (_, Self(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()),
1135            (Self(Large(xs)), Self(Large(ys))) => {
1136                if limbs_xor_neg_neg_in_place_either(xs, ys) {
1137                    *self = other;
1138                }
1139                self.trim();
1140            }
1141        }
1142    }
1143
1144    fn xor_assign_neg_neg_ref(&mut self, other: &Self) {
1145        match (&mut *self, other) {
1146            (Self(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()),
1147            (_, Self(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()),
1148            (Self(Large(xs)), Self(Large(ys))) => {
1149                limbs_xor_neg_neg_in_place_left(xs, ys);
1150                self.trim();
1151            }
1152        }
1153    }
1154
1155    fn xor_neg_neg(&self, other: &Self) -> Self {
1156        match (self, other) {
1157            (&Self(Small(x)), _) => other.xor_neg_limb_neg(x.wrapping_neg()),
1158            (_, &Self(Small(y))) => self.xor_neg_limb_neg(y.wrapping_neg()),
1159            (Self(Large(xs)), Self(Large(ys))) => {
1160                Self::from_owned_limbs_asc(limbs_xor_neg_neg(xs, ys))
1161            }
1162        }
1163    }
1164}
1165
1166impl BitXor<Self> for Integer {
1167    type Output = Self;
1168
1169    /// Takes the bitwise xor of two [`Integer`]s, taking both by value.
1170    ///
1171    /// $$
1172    /// f(x, y) = x \oplus y.
1173    /// $$
1174    ///
1175    /// # Worst-case complexity
1176    /// $T(n) = O(n)$
1177    ///
1178    /// $M(n) = O(1)$
1179    ///
1180    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1181    /// other.significant_bits())`.
1182    ///
1183    /// # Examples
1184    /// ```
1185    /// use malachite_base::num::arithmetic::traits::Pow;
1186    /// use malachite_base::num::basic::traits::One;
1187    /// use malachite_nz::integer::Integer;
1188    ///
1189    /// assert_eq!(Integer::from(-123) ^ Integer::from(-456), 445);
1190    /// assert_eq!(
1191    ///     -Integer::from(10u32).pow(12) ^ -(Integer::from(10u32).pow(12) + Integer::ONE),
1192    ///     8191
1193    /// );
1194    /// ```
1195    #[inline]
1196    fn bitxor(mut self, other: Self) -> Self {
1197        self ^= other;
1198        self
1199    }
1200}
1201
1202impl BitXor<&Self> for Integer {
1203    type Output = Self;
1204
1205    /// Takes the bitwise xor of two [`Integer`]s, taking the first by value and the second by
1206    /// reference.
1207    ///
1208    /// $$
1209    /// f(x, y) = x \oplus y.
1210    /// $$
1211    ///
1212    /// # Worst-case complexity
1213    /// $T(n) = O(n)$
1214    ///
1215    /// $M(m) = O(m)$
1216    ///
1217    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1218    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1219    ///
1220    /// # Examples
1221    /// ```
1222    /// use malachite_base::num::arithmetic::traits::Pow;
1223    /// use malachite_base::num::basic::traits::One;
1224    /// use malachite_nz::integer::Integer;
1225    ///
1226    /// assert_eq!(Integer::from(-123) ^ &Integer::from(-456), 445);
1227    /// assert_eq!(
1228    ///     -Integer::from(10u32).pow(12) ^ &-(Integer::from(10u32).pow(12) + Integer::ONE),
1229    ///     8191
1230    /// );
1231    /// ```
1232    #[inline]
1233    fn bitxor(mut self, other: &Self) -> Self {
1234        self ^= other;
1235        self
1236    }
1237}
1238
1239impl BitXor<Integer> for &Integer {
1240    type Output = Integer;
1241
1242    /// Takes the bitwise xor of two [`Integer`]s, taking the first by reference and the second by
1243    /// value.
1244    ///
1245    /// $$
1246    /// f(x, y) = x \oplus y.
1247    /// $$
1248    ///
1249    /// # Worst-case complexity
1250    /// $T(n) = O(n)$
1251    ///
1252    /// $M(m) = O(m)$
1253    ///
1254    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1255    /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
1256    ///
1257    /// # Examples
1258    /// ```
1259    /// use malachite_base::num::arithmetic::traits::Pow;
1260    /// use malachite_base::num::basic::traits::One;
1261    /// use malachite_nz::integer::Integer;
1262    ///
1263    /// assert_eq!(&Integer::from(-123) ^ Integer::from(-456), 445);
1264    /// assert_eq!(
1265    ///     &-Integer::from(10u32).pow(12) ^ -(Integer::from(10u32).pow(12) + Integer::ONE),
1266    ///     8191
1267    /// );
1268    /// ```
1269    #[inline]
1270    fn bitxor(self, mut other: Integer) -> Integer {
1271        other ^= self;
1272        other
1273    }
1274}
1275
1276impl BitXor<&Integer> for &Integer {
1277    type Output = Integer;
1278
1279    /// Takes the bitwise xor of two [`Integer`]s, taking both by reference.
1280    ///
1281    /// $$
1282    /// f(x, y) = x \oplus y.
1283    /// $$
1284    ///
1285    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1286    /// other.significant_bits())`.
1287    ///
1288    /// # Examples
1289    /// ```
1290    /// use malachite_base::num::arithmetic::traits::Pow;
1291    /// use malachite_base::num::basic::traits::One;
1292    /// use malachite_nz::integer::Integer;
1293    ///
1294    /// assert_eq!(&Integer::from(-123) ^ &Integer::from(-456), 445);
1295    /// assert_eq!(
1296    ///     &-Integer::from(10u32).pow(12) ^ &-(Integer::from(10u32).pow(12) + Integer::ONE),
1297    ///     8191
1298    /// );
1299    /// ```
1300    fn bitxor(self, other: &Integer) -> Integer {
1301        match (self.sign, other.sign) {
1302            (true, true) => Integer {
1303                sign: true,
1304                abs: &self.abs ^ &other.abs,
1305            },
1306            (true, false) => Integer {
1307                sign: false,
1308                abs: self.abs.xor_pos_neg(&other.abs),
1309            },
1310            (false, true) => Integer {
1311                sign: false,
1312                abs: other.abs.xor_pos_neg(&self.abs),
1313            },
1314            (false, false) => Integer {
1315                sign: true,
1316                abs: self.abs.xor_neg_neg(&other.abs),
1317            },
1318        }
1319    }
1320}
1321
1322impl BitXorAssign<Self> for Integer {
1323    /// Bitwise-xors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1324    /// right-hand side by value.
1325    ///
1326    /// $$
1327    /// x \gets x \oplus y.
1328    /// $$
1329    ///
1330    /// # Worst-case complexity
1331    /// $T(n) = O(n)$
1332    ///
1333    /// $M(n) = O(1)$
1334    ///
1335    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1336    /// other.significant_bits())`.
1337    ///
1338    /// # Examples
1339    /// ```
1340    /// use malachite_nz::integer::Integer;
1341    ///
1342    /// let mut x = Integer::from(u32::MAX);
1343    /// x ^= Integer::from(0x0000000f);
1344    /// x ^= Integer::from(0x00000f00);
1345    /// x ^= Integer::from(0x000f_0000);
1346    /// x ^= Integer::from(0x0f000000);
1347    /// assert_eq!(x, 0xf0f0_f0f0u32);
1348    /// ```
1349    fn bitxor_assign(&mut self, other: Self) {
1350        match (self.sign, other.sign) {
1351            (true, true) => self.abs.bitxor_assign(other.abs),
1352            (true, false) => {
1353                self.sign = false;
1354                self.abs.xor_assign_pos_neg(other.abs);
1355            }
1356            (false, true) => self.abs.xor_assign_neg_pos(other.abs),
1357            (false, false) => {
1358                self.sign = true;
1359                self.abs.xor_assign_neg_neg(other.abs);
1360            }
1361        }
1362    }
1363}
1364
1365impl BitXorAssign<&Self> for Integer {
1366    /// Bitwise-xors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1367    /// right-hand side by reference.
1368    ///
1369    /// $$
1370    /// x \gets x \oplus y.
1371    /// $$
1372    ///
1373    /// # Worst-case complexity
1374    /// $T(n) = O(n)$
1375    ///
1376    /// $M(m) = O(m)$
1377    ///
1378    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1379    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1380    ///
1381    /// # Examples
1382    /// ```
1383    /// use malachite_nz::integer::Integer;
1384    ///
1385    /// let mut x = Integer::from(u32::MAX);
1386    /// x ^= &Integer::from(0x0000000f);
1387    /// x ^= &Integer::from(0x00000f00);
1388    /// x ^= &Integer::from(0x000f_0000);
1389    /// x ^= &Integer::from(0x0f000000);
1390    /// assert_eq!(x, 0xf0f0_f0f0u32);
1391    /// ```
1392    fn bitxor_assign(&mut self, other: &Self) {
1393        match (self.sign, other.sign) {
1394            (true, true) => self.abs.bitxor_assign(&other.abs),
1395            (true, false) => {
1396                self.sign = false;
1397                self.abs.xor_assign_pos_neg_ref(&other.abs);
1398            }
1399            (false, true) => self.abs.xor_assign_neg_pos_ref(&other.abs),
1400            (false, false) => {
1401                self.sign = true;
1402                self.abs.xor_assign_neg_neg_ref(&other.abs);
1403            }
1404        }
1405    }
1406}