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 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
662pub_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
719pub_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
783pub_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
839pub_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
921pub_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
957pub_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 #[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 #[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 #[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 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 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 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}