1use 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
35private_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
68private_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
105private_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
136private_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
152private_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
179private_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
208private_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
234private_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
253private_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
281private_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
308private_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
344private_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
428private_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
565private_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
663private_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
720private_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
787private_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
843private_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
925private_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
961private_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 #[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 #[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 #[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 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 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 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}