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::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
34pub_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
67pub_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
104pub_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
135pub_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
151pub_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
178pub_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
207pub_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
233pub_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
252pub_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
280pub_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
307pub_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
343pub_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
427pub_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
564pub_test! {limbs_xor_pos_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
582 let xs_len = xs.len();
583 let ys_len = ys.len();
584 let x_i = slice_leading_zeros(xs);
585 let y_i = slice_leading_zeros(ys);
586 assert!(x_i < xs_len);
587 assert!(y_i < ys_len);
588 if y_i >= xs_len {
589 xs[x_i].wrapping_neg_assign();
590 limbs_not_in_place(&mut xs[x_i + 1..]);
591 xs.extend(repeat_n(Limb::MAX, y_i - xs_len));
592 xs.push(ys[y_i] - 1);
593 xs.extend_from_slice(&ys[y_i + 1..]);
594 return;
595 } else if x_i >= ys_len {
596 xs[..ys_len].copy_from_slice(ys);
597 return;
598 }
599 let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i);
600 match xs_len.cmp(&ys_len) {
601 Less => {
602 if boundary_seen {
603 xs.extend_from_slice(&ys[xs_len..]);
604 } else {
605 for &y in &ys[xs_len..] {
606 xs.push(limbs_xor_pos_neg_helper(!y, &mut boundary_seen));
607 }
608 }
609 }
610 Greater => {
611 if !boundary_seen {
612 for x in &mut xs[ys_len..] {
613 *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen);
614 }
615 }
616 }
617 _ => {}
618 }
619 if slice_test_zero(xs) {
620 xs.push(1);
621 }
622}}
623
624fn limbs_xor_pos_neg_in_place_right_helper(
625 xs: &[Limb],
626 ys: &mut [Limb],
627 x_i: usize,
628 y_i: usize,
629) -> bool {
630 let max_i = max(x_i, y_i);
631 let mut boundary_seen = false;
632 match x_i.cmp(&y_i) {
633 Equal => {
634 ys[y_i] =
635 limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen);
636 }
637 Less => {
638 boundary_seen = true;
639 ys[x_i] = xs[x_i].wrapping_neg();
640 for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..y_i].iter()) {
641 *y = !x;
642 }
643 ys[y_i] -= 1;
644 ys[y_i] ^= xs[y_i];
645 }
646 Greater => {
647 boundary_seen = true;
648 ys[x_i] ^= xs[x_i];
649 }
650 }
651 let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter_mut());
652 if boundary_seen {
653 for (&x, y) in xys {
654 *y ^= x;
655 }
656 } else {
657 for (&x, y) in xys {
658 *y = limbs_xor_pos_neg_helper(x ^ !*y, &mut boundary_seen);
659 }
660 }
661 boundary_seen
662}
663
664pub_test! {limbs_xor_pos_neg_in_place_right(xs: &[Limb], ys: &mut Vec<Limb>) {
682 let xs_len = xs.len();
683 let ys_len = ys.len();
684 let x_i = slice_leading_zeros(xs);
685 let y_i = slice_leading_zeros(ys);
686 assert!(x_i < xs_len);
687 assert!(y_i < ys_len);
688 if y_i >= xs_len {
689 ys[x_i] = xs[x_i].wrapping_neg();
690 for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) {
691 *y = !x;
692 }
693 for y in ys.iter_mut().take(y_i).skip(xs_len) {
694 *y = Limb::MAX;
695 }
696 ys[y_i] -= 1;
697 return;
698 } else if x_i >= ys_len {
699 ys.extend_from_slice(&xs[ys_len..]);
700 return;
701 }
702 let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i);
703 if xs_len > ys_len {
704 if boundary_seen {
705 ys.extend_from_slice(&xs[ys_len..]);
706 } else {
707 for &x in &xs[ys_len..] {
708 ys.push(limbs_xor_pos_neg_helper(!x, &mut boundary_seen));
709 }
710 }
711 } else if xs_len < ys_len && !boundary_seen {
712 for y in &mut ys[xs_len..] {
713 *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen);
714 }
715 }
716 if slice_test_zero(ys) {
717 ys.push(1);
718 }
719}}
720
721pub_test! {limbs_xor_pos_neg_in_place_either(xs: &mut Vec<Limb>, ys: &mut Vec<Limb>) -> bool {
740 let xs_len = xs.len();
741 let ys_len = ys.len();
742 let x_i = slice_leading_zeros(xs);
743 let y_i = slice_leading_zeros(ys);
744 assert!(x_i < xs_len);
745 assert!(y_i < ys_len);
746 if y_i >= xs_len {
747 ys[x_i] = xs[x_i].wrapping_neg();
748 for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) {
749 *y = !x;
750 }
751 for y in &mut ys[xs_len..y_i] {
752 *y = Limb::MAX;
753 }
754 ys[y_i] -= 1;
755 return true;
756 } else if x_i >= ys_len {
757 xs[..ys_len].copy_from_slice(ys);
758 return false;
759 }
760 if xs_len >= ys_len {
761 let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i);
762 if xs_len != ys_len && !boundary_seen {
763 for x in &mut xs[ys_len..] {
764 *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen);
765 }
766 }
767 if slice_test_zero(xs) {
768 xs.push(1);
769 }
770 false
771 } else {
772 let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i);
773 if !boundary_seen {
774 for y in &mut ys[xs_len..] {
775 *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen);
776 }
777 }
778 if slice_test_zero(ys) {
779 ys.push(1);
780 }
781 true
782 }
783}}
784
785pub_test! {limbs_xor_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
802 let xs_len = xs.len();
803 let ys_len = ys.len();
804 let x_i = slice_leading_zeros(xs);
805 let y_i = slice_leading_zeros(ys);
806 assert!(x_i < xs_len);
807 assert!(y_i < ys_len);
808 if y_i >= xs_len {
809 let (result, borrow) = limbs_sub(ys, xs);
810 assert!(!borrow);
811 return result;
812 } else if x_i >= ys_len {
813 let (result, borrow) = limbs_sub(xs, ys);
814 assert!(!borrow);
815 return result;
816 }
817 let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
818 let mut out = vec![0; min_i];
819 if x_i == y_i {
820 out.push(xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg());
821 } else {
822 let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) };
823 out.push(min_zs[min_i].wrapping_neg());
824 out.extend(min_zs[min_i + 1..max_i].iter().map(|z| !z));
825 out.push((max_zs[max_i] - 1) ^ min_zs[max_i]);
826 }
827 out.extend(
828 xs[max_i + 1..]
829 .iter()
830 .zip(ys[max_i + 1..].iter())
831 .map(|(x, y)| x ^ y),
832 );
833 match xs_len.cmp(&ys_len) {
834 Less => out.extend_from_slice(&ys[xs_len..]),
835 Greater => out.extend_from_slice(&xs[ys_len..]),
836 _ => {}
837 }
838 out
839}}
840
841pub_test! {limbs_xor_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
859 let xs_len = xs.len();
860 let ys_len = ys.len();
861 assert!(out.len() >= xs_len);
862 assert!(out.len() >= ys_len);
863 let x_i = slice_leading_zeros(xs);
864 let y_i = slice_leading_zeros(ys);
865 assert!(x_i < xs_len);
866 assert!(y_i < ys_len);
867 if y_i >= xs_len {
868 assert!(!limbs_sub_greater_to_out(out, ys, xs));
869 return;
870 } else if x_i >= ys_len {
871 assert!(!limbs_sub_greater_to_out(out, xs, ys));
872 return;
873 }
874 let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
875 slice_set_zero(&mut out[..min_i]);
876 if x_i == y_i {
877 out[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg();
878 } else {
879 let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) };
880 out[min_i] = min_zs[min_i].wrapping_neg();
881 for (out, &z) in out[min_i + 1..max_i]
882 .iter_mut()
883 .zip(min_zs[min_i + 1..max_i].iter())
884 {
885 *out = !z;
886 }
887 out[max_i] = (max_zs[max_i] - 1) ^ min_zs[max_i];
888 }
889 for (out, (&x, &y)) in out[max_i + 1..]
890 .iter_mut()
891 .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()))
892 {
893 *out = x ^ y;
894 }
895 match xs_len.cmp(&ys_len) {
896 Less => out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]),
897 Greater => out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]),
898 _ => {}
899 }
900}}
901
902fn limbs_xor_neg_neg_in_place_helper(xs: &mut [Limb], ys: &[Limb], x_i: usize, y_i: usize) {
903 let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
904 if x_i == y_i {
905 xs[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg();
906 } else if x_i <= y_i {
907 xs[min_i].wrapping_neg_assign();
908 limbs_not_in_place(&mut xs[min_i + 1..max_i]);
909 xs[max_i] ^= ys[max_i] - 1;
910 } else {
911 xs[min_i] = ys[min_i].wrapping_neg();
912 for (x, &y) in xs[min_i + 1..max_i].iter_mut().zip(ys[min_i + 1..].iter()) {
913 *x = !y;
914 }
915 xs[max_i] -= 1;
916 xs[max_i] ^= ys[max_i];
917 }
918 for (x, &y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
919 *x ^= y;
920 }
921}
922
923pub_test! {limbs_xor_neg_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
941 let xs_len = xs.len();
942 let ys_len = ys.len();
943 let x_i = slice_leading_zeros(xs);
944 let y_i = slice_leading_zeros(ys);
945 assert!(x_i < xs_len);
946 assert!(y_i < ys_len);
947 if y_i >= xs_len {
948 assert!(!limbs_vec_sub_in_place_right(ys, xs));
949 } else if x_i >= ys_len {
950 assert!(!limbs_sub_greater_in_place_left(xs, ys));
951 } else {
952 limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i);
953 if xs_len < ys_len {
954 xs.extend_from_slice(&ys[xs_len..]);
955 }
956 }
957}}
958
959pub_test! {limbs_xor_neg_neg_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool {
977 let xs_len = xs.len();
978 let ys_len = ys.len();
979 let x_i = slice_leading_zeros(xs);
980 let y_i = slice_leading_zeros(ys);
981 assert!(x_i < xs_len);
982 assert!(y_i < ys_len);
983 if y_i >= xs_len {
984 assert!(!limbs_sub_greater_in_place_left(ys, xs));
985 true
986 } else if x_i >= ys_len {
987 assert!(!limbs_sub_greater_in_place_left(xs, ys));
988 false
989 } else if xs_len >= ys_len {
990 limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i);
991 false
992 } else {
993 limbs_xor_neg_neg_in_place_helper(ys, xs, y_i, x_i);
994 true
995 }
996}}
997
998impl Natural {
999 fn xor_assign_neg_limb_pos(&mut self, other: Limb) {
1000 match self {
1001 &mut Natural::ZERO => {}
1002 Natural(Small(small)) => {
1003 let result = small.wrapping_neg() ^ other;
1004 if result == 0 {
1005 *self = Natural(Large(vec![0, 1]));
1006 } else {
1007 *small = result.wrapping_neg();
1008 }
1009 }
1010 Natural(Large(limbs)) => {
1011 limbs_vec_neg_xor_limb_in_place(limbs, other);
1012 self.trim();
1013 }
1014 }
1015 }
1016
1017 fn xor_neg_limb_pos(&self, other: Limb) -> Natural {
1018 match self {
1019 &Natural::ZERO => self.clone(),
1020 Natural(Small(small)) => {
1021 let result = small.wrapping_neg() ^ other;
1022 Natural(if result == 0 {
1023 Large(vec![0, 1])
1024 } else {
1025 Small(result.wrapping_neg())
1026 })
1027 }
1028 Natural(Large(limbs)) => {
1029 Natural::from_owned_limbs_asc(limbs_neg_xor_limb(limbs, other))
1030 }
1031 }
1032 }
1033
1034 fn xor_assign_pos_limb_neg(&mut self, other: Limb) {
1035 match self {
1036 Natural(Small(small)) => {
1037 let result = *small ^ other;
1038 if result == 0 {
1039 *self = Natural(Large(vec![0, 1]));
1040 } else {
1041 *small = result.wrapping_neg();
1042 }
1043 }
1044 Natural(Large(limbs)) => {
1045 limbs_vec_pos_xor_limb_neg_in_place(limbs, other);
1046 self.trim();
1047 }
1048 }
1049 }
1050
1051 fn xor_pos_limb_neg(&self, other: Limb) -> Natural {
1052 Natural(match self {
1053 Natural(Small(small)) => {
1054 let result = small ^ other;
1055 if result == 0 {
1056 Large(vec![0, 1])
1057 } else {
1058 Small(result.wrapping_neg())
1059 }
1060 }
1061 Natural(Large(limbs)) => Large(limbs_pos_xor_limb_neg(limbs, other)),
1062 })
1063 }
1064
1065 fn xor_assign_neg_limb_neg(&mut self, other: Limb) {
1066 match &mut *self {
1067 Natural(Small(small)) => *small = small.wrapping_neg() ^ other,
1068 Natural(Large(limbs)) => {
1069 limbs_neg_xor_limb_neg_in_place(limbs, other);
1070 self.trim();
1071 }
1072 }
1073 }
1074
1075 fn xor_neg_limb_neg(&self, other: Limb) -> Natural {
1076 match self {
1077 Natural(Small(small)) => Natural(Small(small.wrapping_neg() ^ other)),
1078 Natural(Large(limbs)) => {
1079 Natural::from_owned_limbs_asc(limbs_neg_xor_limb_neg(limbs, other))
1080 }
1081 }
1082 }
1083
1084 fn xor_assign_pos_neg(&mut self, mut other: Natural) {
1085 match (&mut *self, &mut other) {
1086 (Natural(Small(x)), _) => {
1087 other.xor_assign_neg_limb_pos(*x);
1088 *self = other;
1089 }
1090 (_, Natural(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()),
1091 (Natural(Large(xs)), Natural(Large(ys))) => {
1092 if limbs_xor_pos_neg_in_place_either(xs, ys) {
1093 *self = other;
1094 }
1095 self.trim();
1096 }
1097 }
1098 }
1099
1100 fn xor_assign_pos_neg_ref(&mut self, other: &Natural) {
1101 match (&mut *self, other) {
1102 (Natural(Small(x)), _) => *self = other.xor_neg_limb_pos(*x),
1103 (_, Natural(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()),
1104 (Natural(Large(xs)), Natural(Large(ys))) => {
1105 limbs_xor_pos_neg_in_place_left(xs, ys);
1106 self.trim();
1107 }
1108 }
1109 }
1110
1111 fn xor_assign_neg_pos(&mut self, mut other: Natural) {
1112 other.xor_assign_pos_neg_ref(&*self);
1113 *self = other;
1114 }
1115
1116 fn xor_assign_neg_pos_ref(&mut self, other: &Natural) {
1117 match (&mut *self, other) {
1118 (Natural(Small(x)), _) => *self = other.xor_pos_limb_neg(x.wrapping_neg()),
1119 (_, Natural(Small(y))) => self.xor_assign_neg_limb_pos(*y),
1120 (Natural(Large(xs)), Natural(Large(ys))) => {
1121 limbs_xor_pos_neg_in_place_right(ys, xs);
1122 self.trim();
1123 }
1124 }
1125 }
1126
1127 fn xor_pos_neg(&self, other: &Natural) -> Natural {
1128 match (self, other) {
1129 (&Natural(Small(x)), _) => other.xor_neg_limb_pos(x),
1130 (_, &Natural(Small(y))) => self.xor_pos_limb_neg(y.wrapping_neg()),
1131 (Natural(Large(xs)), Natural(Large(ys))) => {
1132 Natural::from_owned_limbs_asc(limbs_xor_pos_neg(xs, ys))
1133 }
1134 }
1135 }
1136
1137 fn xor_assign_neg_neg(&mut self, mut other: Natural) {
1138 match (&mut *self, &mut other) {
1139 (Natural(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()),
1140 (_, Natural(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()),
1141 (Natural(Large(xs)), Natural(Large(ys))) => {
1142 if limbs_xor_neg_neg_in_place_either(xs, ys) {
1143 *self = other;
1144 }
1145 self.trim();
1146 }
1147 }
1148 }
1149
1150 fn xor_assign_neg_neg_ref(&mut self, other: &Natural) {
1151 match (&mut *self, other) {
1152 (Natural(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()),
1153 (_, Natural(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()),
1154 (Natural(Large(xs)), Natural(Large(ys))) => {
1155 limbs_xor_neg_neg_in_place_left(xs, ys);
1156 self.trim();
1157 }
1158 }
1159 }
1160
1161 fn xor_neg_neg(&self, other: &Natural) -> Natural {
1162 match (self, other) {
1163 (&Natural(Small(x)), _) => other.xor_neg_limb_neg(x.wrapping_neg()),
1164 (_, &Natural(Small(y))) => self.xor_neg_limb_neg(y.wrapping_neg()),
1165 (Natural(Large(xs)), Natural(Large(ys))) => {
1166 Natural::from_owned_limbs_asc(limbs_xor_neg_neg(xs, ys))
1167 }
1168 }
1169 }
1170}
1171
1172impl BitXor<Integer> for Integer {
1173 type Output = Integer;
1174
1175 #[inline]
1202 fn bitxor(mut self, other: Integer) -> Integer {
1203 self ^= other;
1204 self
1205 }
1206}
1207
1208impl BitXor<&Integer> for Integer {
1209 type Output = Integer;
1210
1211 #[inline]
1239 fn bitxor(mut self, other: &Integer) -> Integer {
1240 self ^= other;
1241 self
1242 }
1243}
1244
1245impl BitXor<Integer> for &Integer {
1246 type Output = Integer;
1247
1248 #[inline]
1276 fn bitxor(self, mut other: Integer) -> Integer {
1277 other ^= self;
1278 other
1279 }
1280}
1281
1282impl BitXor<&Integer> for &Integer {
1283 type Output = Integer;
1284
1285 fn bitxor(self, other: &Integer) -> Integer {
1307 match (self.sign, other.sign) {
1308 (true, true) => Integer {
1309 sign: true,
1310 abs: &self.abs ^ &other.abs,
1311 },
1312 (true, false) => Integer {
1313 sign: false,
1314 abs: self.abs.xor_pos_neg(&other.abs),
1315 },
1316 (false, true) => Integer {
1317 sign: false,
1318 abs: other.abs.xor_pos_neg(&self.abs),
1319 },
1320 (false, false) => Integer {
1321 sign: true,
1322 abs: self.abs.xor_neg_neg(&other.abs),
1323 },
1324 }
1325 }
1326}
1327
1328impl BitXorAssign<Integer> for Integer {
1329 fn bitxor_assign(&mut self, other: Integer) {
1356 match (self.sign, other.sign) {
1357 (true, true) => self.abs.bitxor_assign(other.abs),
1358 (true, false) => {
1359 self.sign = false;
1360 self.abs.xor_assign_pos_neg(other.abs);
1361 }
1362 (false, true) => self.abs.xor_assign_neg_pos(other.abs),
1363 (false, false) => {
1364 self.sign = true;
1365 self.abs.xor_assign_neg_neg(other.abs);
1366 }
1367 }
1368 }
1369}
1370
1371impl BitXorAssign<&Integer> for Integer {
1372 fn bitxor_assign(&mut self, other: &Integer) {
1399 match (self.sign, other.sign) {
1400 (true, true) => self.abs.bitxor_assign(&other.abs),
1401 (true, false) => {
1402 self.sign = false;
1403 self.abs.xor_assign_pos_neg_ref(&other.abs);
1404 }
1405 (false, true) => self.abs.xor_assign_neg_pos_ref(&other.abs),
1406 (false, false) => {
1407 self.sign = true;
1408 self.abs.xor_assign_neg_neg_ref(&other.abs);
1409 }
1410 }
1411 }
1412}