malachite_nz/integer/logic/and.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, 2003, 2005, 2012, 2015-2018 Free
6// Software 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::{limbs_add_limb_to_out, limbs_slice_add_limb_in_place};
18use crate::platform::Limb;
19use alloc::vec::Vec;
20use core::cmp::{Ordering::*, max};
21use core::ops::{BitAnd, BitAndAssign};
22use malachite_base::num::arithmetic::traits::WrappingNegAssign;
23use malachite_base::num::basic::traits::Zero;
24use malachite_base::num::logic::traits::NotAssign;
25use malachite_base::slices::{slice_leading_zeros, slice_set_zero};
26
27// Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, returns the
28// limbs of the bitwise and of the `Integer` and a negative number whose lowest limb is given by `y`
29// and whose other limbs are full of `true` bits. `xs` may not be empty.
30//
31// # Worst-case complexity
32// $T(n) = O(n)$
33//
34// $M(n) = O(n)$
35//
36// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
37//
38// # Panics
39// Panics if `xs` is empty.
40private_test_fn! {limbs_pos_and_limb_neg(xs: &[Limb], y: Limb) -> Vec<Limb> {
41 let mut out = xs.to_vec();
42 out[0] &= y;
43 out
44}}
45
46// Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, writes the
47// limbs of the bitwise and of the `Integer` and a negative number whose lowest limb is given by `y`
48// and whose other limbs are full of `true` bits, to an output slice. `xs` may not be empty. The
49// output slice must be at least as long as the input slice.
50//
51// # Worst-case complexity
52// $T(n) = O(n)$
53//
54// $M(n) = O(1)$
55//
56// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
57//
58// # Panics
59// Panics if `xs` is empty or if `out` is shorter than `xs`.
60private_test_fn! {limbs_pos_and_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) {
61 let len = xs.len();
62 assert!(out.len() >= len);
63 let (xs_head, xs_tail) = xs.split_first().unwrap();
64 let (out_head, out_tail) = out[..len].split_first_mut().unwrap();
65 *out_head = xs_head & y;
66 out_tail.copy_from_slice(xs_tail);
67}}
68
69// Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, writes the
70// limbs of the bitwise and of the `Integer` and a negative number whose lowest limb is given by `y`
71// and whose other limbs are full of `true` bits, to the input slice. `xs` may not be empty.
72//
73// # Worst-case complexity
74// Constant time and additional memory.
75//
76// # Panics
77// Panics if `xs` is empty.
78private_test_const_fn! {limbs_pos_and_limb_neg_in_place(xs: &mut [Limb], ys: Limb) {
79 xs[0] &= ys;
80}}
81
82// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
83// `Integer`, returns the limbs of the bitwise and of the `Integer` and a negative number whose
84// lowest limb is given by `y` and whose other limbs are full of `true` bits. `xs` may not be empty
85// or only contain zeros.
86//
87// # Worst-case complexity
88// $T(n) = O(n)$
89//
90// $M(n) = O(n)$
91//
92// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
93//
94// # Panics
95// Panics if `xs` is empty.
96private_test_fn! {limbs_neg_and_limb_neg(xs: &[Limb], y: Limb) -> Vec<Limb> {
97 let mut out = xs.to_vec();
98 limbs_vec_neg_and_limb_neg_in_place(&mut out, y);
99 out
100}}
101
102// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
103// `Integer`, writes the limbs of the bitwise and of the `Integer` and a negative number whose
104// lowest limb is given by `y` and whose other limbs are full of `true` bits to an output slice.
105// `xs` may not be empty or only contain zeros. Returns whether a carry occurs. The output slice
106// must be at least as long as the input slice.
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()`.
114//
115// # Panics
116// Panics if `xs` is empty or if `out` is shorter than `xs`.
117private_test_fn! {limbs_neg_and_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) -> bool {
118 let out = &mut out[..xs.len()];
119 if xs[0] == 0 {
120 out.copy_from_slice(xs);
121 false
122 } else {
123 let (xs_head, xs_tail) = xs.split_first().unwrap();
124 let (out_head, out_tail) = out.split_first_mut().unwrap();
125 let result_head = xs_head.wrapping_neg() & y;
126 if result_head == 0 {
127 *out_head = 0;
128 limbs_add_limb_to_out(out_tail, xs_tail, 1)
129 } else {
130 *out_head = result_head.wrapping_neg();
131 out_tail.copy_from_slice(xs_tail);
132 false
133 }
134 }
135}}
136
137// Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an
138// `Integer`, takes the bitwise and of the `Integer` and a negative number whose lowest limb is
139// given by `y` and whose other limbs are full of `true` bits, in place. `xs` may not be empty or
140// only contain zeros. Returns whether there is a carry.
141//
142// # Worst-case complexity
143// $T(n) = O(n)$
144//
145// $M(n) = O(1)$
146//
147// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
148//
149// # Panics
150// Panics if `xs` is empty.
151private_test_fn! {limbs_slice_neg_and_limb_neg_in_place(xs: &mut [Limb], y: Limb) -> bool {
152 let (xs_head, xs_tail) = xs.split_first_mut().unwrap();
153 if *xs_head == 0 {
154 false
155 } else {
156 *xs_head = xs_head.wrapping_neg() & y;
157 if *xs_head == 0 {
158 limbs_slice_add_limb_in_place(xs_tail, 1)
159 } else {
160 xs_head.wrapping_neg_assign();
161 false
162 }
163 }
164}}
165
166// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of the negative of an
167// `Integer`, takes the bitwise and of the `Integer` and a negative number whose lowest limb is
168// given by `y` and whose other limbs are full of `true` bits, in place. `xs` may not be empty or
169// only contain zeros. If there is a carry, increases the length of the `Vec` by 1.
170//
171// # Worst-case complexity
172// $T(n) = O(n)$
173//
174// $M(n) = O(1)$
175//
176// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
177//
178// # Panics
179// Panics if `xs` is empty.
180private_test_fn! {limbs_vec_neg_and_limb_neg_in_place(xs: &mut Vec<Limb>, y: Limb) {
181 if limbs_slice_neg_and_limb_neg_in_place(xs, y) {
182 xs.push(1);
183 }
184}}
185
186// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
187// negative of another, returns the limbs of the bitwise and of the `Integer`s. `xs` and `ys` may
188// not be empty or only contain zeros.
189//
190// # Worst-case complexity
191// $T(n) = O(n)$
192//
193// $M(n) = O(n)$
194//
195// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
196//
197// # Panics
198// Panics if `xs` or `ys` are empty or contain only zeros.
199//
200// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res` is returned, the first
201// input is positive, and the second is negative.
202private_test_fn! {limbs_and_pos_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
203 let xs_len = xs.len();
204 let ys_len = ys.len();
205 let x_i = slice_leading_zeros(xs);
206 let y_i = slice_leading_zeros(ys);
207 assert!(x_i < xs_len);
208 assert!(y_i < ys_len);
209 if y_i >= xs_len {
210 return Vec::new();
211 } else if x_i >= ys_len {
212 return xs.to_vec();
213 }
214 let max_i = max(x_i, y_i);
215 let mut out = vec![0; max_i];
216 out.push(
217 xs[max_i]
218 & if x_i <= y_i {
219 ys[max_i].wrapping_neg()
220 } else {
221 !ys[max_i]
222 },
223 );
224 out.extend(
225 xs[max_i + 1..]
226 .iter()
227 .zip(ys[max_i + 1..].iter())
228 .map(|(&x, &y)| x & !y),
229 );
230 if xs_len > ys_len {
231 out.extend_from_slice(&xs[ys_len..]);
232 }
233 out
234}}
235
236// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
237// negative of another, writes the limbs of the bitwise and of the `Integer`s to an output slice.
238// `xs` and `ys` may not be empty or only contain zeros. The output slice must be at least as long
239// as the first input slice. `xs.len()` limbs will be written; if the number of significant limbs of
240// the result is lower, some of the written limbs will be zero.
241//
242// # Worst-case complexity
243// $T(n) = O(n)$
244//
245// $M(n) = O(1)$
246//
247// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
248//
249// # Panics
250// Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than `xs`.
251//
252// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where the first input is positive
253// and the second is negative.
254private_test_fn! {limbs_and_pos_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
255 let xs_len = xs.len();
256 let ys_len = ys.len();
257 assert!(out.len() >= xs_len);
258 let x_i = slice_leading_zeros(xs);
259 let y_i = slice_leading_zeros(ys);
260 assert!(x_i < xs_len);
261 assert!(y_i < ys_len);
262 if y_i >= xs_len {
263 slice_set_zero(&mut out[..xs_len]);
264 return;
265 } else if x_i >= ys_len {
266 out[..xs_len].copy_from_slice(xs);
267 return;
268 }
269 let max_i = max(x_i, y_i);
270 slice_set_zero(&mut out[..max_i]);
271 out[max_i] = xs[max_i]
272 & if x_i <= y_i {
273 ys[max_i].wrapping_neg()
274 } else {
275 !ys[max_i]
276 };
277 for (z, (x, y)) in out[max_i + 1..]
278 .iter_mut()
279 .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()))
280 {
281 *z = x & !y;
282 }
283 if xs_len > ys_len {
284 out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]);
285 }
286}}
287
288// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
289// negative of another, writes the limbs of the bitwise and of the `Integer`s to the first (left)
290// slice. `xs` and `ys` may not be empty or only contain zeros.
291//
292// # Worst-case complexity
293// $T(n) = O(n)$
294//
295// $M(n) = O(1)$
296//
297// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
298//
299// # Panics
300// Panics if `xs` or `ys` are empty or contain only zeros.
301//
302// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1`, the first input
303// is positive, and the second is negative.
304private_test_fn! {limbs_and_pos_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) {
305 let xs_len = xs.len();
306 let ys_len = ys.len();
307 let x_i = slice_leading_zeros(xs);
308 let y_i = slice_leading_zeros(ys);
309 assert!(x_i < xs_len);
310 assert!(y_i < ys_len);
311 if y_i >= xs_len {
312 slice_set_zero(xs);
313 return;
314 } else if x_i >= ys_len {
315 return;
316 }
317 let max_i = max(x_i, y_i);
318 slice_set_zero(&mut xs[..max_i]);
319 xs[max_i] &= if x_i <= y_i {
320 ys[max_i].wrapping_neg()
321 } else {
322 !ys[max_i]
323 };
324 for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
325 *x &= !y;
326 }
327}}
328
329// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
330// negative of another, writes the lowest min(`xs.len()`, `ys.len()`) limbs of the bitwise and of
331// the `Integer`s to the second (right) slice. `xs` and `ys` may not be empty or only contain zeros.
332// If `ys` is shorter than `xs`, the result may be too long to fit in `ys`. The extra limbs in this
333// case are just `xs[ys.len()..]`.
334//
335// # Worst-case complexity
336// $T(n) = O(n)$
337//
338// $M(n) = O(1)$
339//
340// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
341//
342// # Panics
343// Panics if `xs` or `ys` are empty or contain only zeros.
344//
345// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op2`, the first input
346// is positive, the second is negative, and the length of `op2` is not changed; instead, a carry is
347// returned.
348private_test_fn! {limbs_slice_and_pos_neg_in_place_right(xs: &[Limb], ys: &mut [Limb]) {
349 let xs_len = xs.len();
350 let ys_len = ys.len();
351 let x_i = slice_leading_zeros(xs);
352 let y_i = slice_leading_zeros(ys);
353 assert!(x_i < xs_len);
354 assert!(y_i < ys_len);
355 if y_i >= xs_len || x_i >= ys_len {
356 slice_set_zero(ys);
357 return;
358 }
359 let max_i = max(x_i, y_i);
360 slice_set_zero(&mut ys[..max_i]);
361 {
362 let ys_max_i = &mut ys[max_i];
363 if x_i <= y_i {
364 ys_max_i.wrapping_neg_assign();
365 } else {
366 ys_max_i.not_assign();
367 }
368 *ys_max_i &= xs[max_i];
369 }
370 for (x, y) in xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter_mut()) {
371 *y = !*y & x;
372 }
373}}
374
375// Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of one
376// `Integer` and the negative of another, writes the limbs of the bitwise and of the `Integer`s to
377// the `Vec`. `xs` and `ys` may not be empty or only contain zeros.
378//
379// # Worst-case complexity
380// $T(n) = O(n)$
381//
382// $M(n) = O(n)$
383//
384// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
385//
386// # Panics
387// Panics if `xs` or `ys` are empty or contain only zeros.
388//
389// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op2`, the first input
390// is positive, and the second is negative.
391private_test_fn! {limbs_vec_and_pos_neg_in_place_right(xs: &[Limb], ys: &mut Vec<Limb>) {
392 limbs_slice_and_pos_neg_in_place_right(xs, ys);
393 let xs_len = xs.len();
394 let ys_len = ys.len();
395 match xs_len.cmp(&ys_len) {
396 Greater => {
397 let ys_len = ys.len();
398 ys.extend(xs[ys_len..].iter());
399 }
400 Less => {
401 ys.truncate(xs_len);
402 }
403 _ => {}
404 }
405}}
406
407const fn limbs_and_neg_neg_helper(input: Limb, boundary_limb_seen: &mut bool) -> Limb {
408 if *boundary_limb_seen {
409 input
410 } else {
411 let result = input.wrapping_add(1);
412 if result != 0 {
413 *boundary_limb_seen = true;
414 }
415 result
416 }
417}
418
419// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
420// `Integer`s, returns the limbs of the bitwise and of the `Integer`s. `xs` and `ys` may not be
421// empty or only contain zeros.
422//
423// # Worst-case complexity
424// $T(n) = O(n)$
425//
426// $M(n) = O(n)$
427//
428// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
429//
430// # Panics
431// Panics if `xs` or `ys` are empty or contain only zeros.
432//
433// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res` is returned and both
434// inputs are negative.
435private_test_fn! {limbs_and_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
436 let xs_len = xs.len();
437 let ys_len = ys.len();
438 let x_i = slice_leading_zeros(xs);
439 let y_i = slice_leading_zeros(ys);
440 assert!(x_i < xs_len);
441 assert!(y_i < ys_len);
442 if y_i >= xs_len {
443 return ys.to_vec();
444 } else if x_i >= ys_len {
445 return xs.to_vec();
446 }
447 let max_i = max(x_i, y_i);
448 let mut out = vec![0; max_i];
449 let x = if x_i >= y_i {
450 xs[max_i].wrapping_sub(1)
451 } else {
452 xs[max_i]
453 };
454 let y = if x_i <= y_i {
455 ys[max_i].wrapping_sub(1)
456 } else {
457 ys[max_i]
458 };
459 let mut boundary_limb_seen = false;
460 out.push(limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen));
461 let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter());
462 if boundary_limb_seen {
463 out.extend(xys.map(|(&x, &y)| x | y));
464 } else {
465 for (&x, &y) in xys {
466 out.push(limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen));
467 }
468 }
469 if xs_len != ys_len {
470 let zs = if xs_len > ys_len {
471 &xs[ys_len..]
472 } else {
473 &ys[xs_len..]
474 };
475 if boundary_limb_seen {
476 out.extend_from_slice(zs);
477 } else {
478 for &z in zs {
479 out.push(limbs_and_neg_neg_helper(z, &mut boundary_limb_seen));
480 }
481 }
482 }
483 if !boundary_limb_seen {
484 out.push(1);
485 }
486 out
487}}
488
489// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
490// `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise and of the `Integer`s to
491// an output slice. `xs` and `ys` may not be empty or only contain zeros. Returns whether the
492// least-significant max(`xs.len()`, `ys.len()`) limbs of the output are not all zero. The output
493// slice must be at least as long as the longer input slice.
494//
495// # Worst-case complexity
496// $T(n) = O(n)$
497//
498// $M(n) = O(1)$
499//
500// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
501//
502// # Panics
503// Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of
504// `xs` and `ys`.
505//
506// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are negative.
507private_test_fn! {limbs_and_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool {
508 let xs_len = xs.len();
509 let ys_len = ys.len();
510 let x_i = slice_leading_zeros(xs);
511 let y_i = slice_leading_zeros(ys);
512 assert!(x_i < xs_len);
513 assert!(y_i < ys_len);
514 if y_i >= xs_len {
515 out[..ys_len].copy_from_slice(ys);
516 if xs_len > ys_len {
517 slice_set_zero(&mut out[ys_len..xs_len]);
518 }
519 return true;
520 } else if x_i >= ys_len {
521 out[..xs_len].copy_from_slice(xs);
522 if ys_len > xs_len {
523 slice_set_zero(&mut out[xs_len..ys_len]);
524 }
525 return true;
526 }
527 let max_i = max(x_i, y_i);
528 slice_set_zero(&mut out[..max_i]);
529 let x = if x_i >= y_i {
530 xs[max_i].wrapping_sub(1)
531 } else {
532 xs[max_i]
533 };
534 let y = if x_i <= y_i {
535 ys[max_i].wrapping_sub(1)
536 } else {
537 ys[max_i]
538 };
539 let mut boundary_limb_seen = false;
540 out[max_i] = limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen);
541 let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter());
542 if boundary_limb_seen {
543 for (z, (x, y)) in out[max_i + 1..].iter_mut().zip(xys) {
544 *z = x | y;
545 }
546 } else {
547 for (z, (x, y)) in out[max_i + 1..].iter_mut().zip(xys) {
548 *z = limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen);
549 }
550 }
551 let (xs, xs_len, ys_len) = if xs_len >= ys_len {
552 (xs, xs_len, ys_len)
553 } else {
554 (ys, ys_len, xs_len)
555 };
556 if xs_len != ys_len {
557 let zs = &xs[ys_len..];
558 if boundary_limb_seen {
559 out[ys_len..xs_len].copy_from_slice(zs);
560 } else {
561 for (z_out, &z_in) in out[ys_len..xs_len].iter_mut().zip(zs.iter()) {
562 *z_out = limbs_and_neg_neg_helper(z_in, &mut boundary_limb_seen);
563 }
564 }
565 }
566 boundary_limb_seen
567}}
568
569// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
570// `Integer`s, writes the lower `xs.len()` limbs of the bitwise and of the `Integer`s to the first
571// (left) slice. `xs` and `ys` may not be empty or only contain zeros, and `xs` must be at least as
572// long as `ys`. Returns whether the least-significant `xs.len()` limbs of the output are not all
573// zero.
574//
575// # Worst-case complexity
576// $T(n) = O(n)$
577//
578// $M(n) = O(1)$
579//
580// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
581//
582// # Panics
583// Panics if `xs` or `ys` are empty or contain only zeros, or if `xs` is shorter than `ys`.
584//
585// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1`, both inputs are
586// negative, and the length of `op1` is not changed; instead, a carry is returned.
587private_test_fn! {limbs_slice_and_neg_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool {
588 let xs_len = xs.len();
589 let ys_len = ys.len();
590 assert!(xs_len >= ys_len);
591 let x_i = slice_leading_zeros(xs);
592 let y_i = slice_leading_zeros(ys);
593 assert!(x_i < xs_len);
594 assert!(y_i < ys_len);
595 if x_i >= ys_len {
596 return true;
597 }
598 let max_i = max(x_i, y_i);
599 if y_i > x_i {
600 slice_set_zero(&mut xs[x_i..y_i]);
601 }
602 let x = if x_i >= y_i {
603 xs[max_i].wrapping_sub(1)
604 } else {
605 xs[max_i]
606 };
607 let y = if x_i <= y_i {
608 ys[max_i].wrapping_sub(1)
609 } else {
610 ys[max_i]
611 };
612 let mut boundary_limb_seen = false;
613 xs[max_i] = limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen);
614 let xys = xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter());
615 if boundary_limb_seen {
616 for (x, &y) in xys {
617 *x |= y;
618 }
619 } else {
620 for (x, &y) in xys {
621 *x = limbs_and_neg_neg_helper(*x | y, &mut boundary_limb_seen);
622 }
623 }
624 if xs_len > ys_len && !boundary_limb_seen {
625 for x in &mut xs[ys_len..] {
626 *x = limbs_and_neg_neg_helper(*x, &mut boundary_limb_seen);
627 }
628 }
629 boundary_limb_seen
630}}
631
632// Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of the
633// negatives of two `Integer`s, writes the limbs of the bitwise and of the `Integer`s to the `Vec`.
634// `xs` and `ys` may not be empty or only contain zeros.
635//
636// # Worst-case complexity
637// $T(n) = O(n)$
638//
639// $M(n) = O(n)$
640//
641// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
642//
643// # Panics
644// Panics if `xs` or `ys` are empty or contain only zeros.
645//
646// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1` and both inputs
647// are negative.
648private_test_fn! {limbs_vec_and_neg_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
649 let xs_len = xs.len();
650 let ys_len = ys.len();
651 let y_i = slice_leading_zeros(ys);
652 assert!(y_i < ys_len);
653 if y_i >= xs_len {
654 xs.resize(ys_len, 0);
655 xs.copy_from_slice(ys);
656 return;
657 }
658 let boundary_limb_seen = if ys_len > xs_len {
659 let mut boundary_limb_seen = limbs_slice_and_neg_neg_in_place_left(xs, &ys[..xs_len]);
660 let zs = &ys[xs_len..];
661 if boundary_limb_seen {
662 xs.extend_from_slice(zs);
663 } else {
664 for &z in zs {
665 xs.push(limbs_and_neg_neg_helper(z, &mut boundary_limb_seen));
666 }
667 }
668 boundary_limb_seen
669 } else {
670 limbs_slice_and_neg_neg_in_place_left(xs, ys)
671 };
672 if !boundary_limb_seen {
673 xs.push(1);
674 }
675}}
676
677// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
678// `Integer`s, writes the lower max(`xs.len()`, `ys.len()`) limbs of the bitwise and of the
679// `Integer`s to the longer slice (or the first one, if they are equally long). `xs` and `ys` may
680// not be empty or only contain zeros. Returns a pair of `bool`s. The first is `false` when the
681// output is to the first slice and `true` when it's to the second slice, and the second is whether
682// the least-significant max(`xs.len()`, `ys.len()`) limbs of the output are not all zero.
683//
684// # Worst-case complexity
685// $T(n) = O(n)$
686//
687// $M(n) = O(1)$
688//
689// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
690//
691// # Panics
692// Panics if `xs` or `ys` are empty or contain only zeros.
693//
694// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are negative, the
695// result is written to the longer input slice, and the length of `op1` is not changed; instead, a
696// carry is returned.
697private_test_fn! {limbs_slice_and_neg_neg_in_place_either(
698 xs: &mut [Limb],
699 ys: &mut [Limb]
700) -> (bool, bool) {
701 if xs.len() >= ys.len() {
702 (false, limbs_slice_and_neg_neg_in_place_left(xs, ys))
703 } else {
704 (true, limbs_slice_and_neg_neg_in_place_left(ys, xs))
705 }
706}}
707
708// Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of the negatives of two
709// `Integer`s, writes the limbs of the bitwise and of the `Integer`s to the longer `Vec` (or the
710// first one, if they are equally long). `xs` and `ys` may not be empty or only contain zeros.
711// Returns a `bool` which is `false` when the output is to the first slice and `true` when it's to
712// the second slice.
713//
714// # Worst-case complexity
715// $T(n) = O(n)$
716//
717// $M(n) = O(1)$
718//
719// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
720//
721// # Panics
722// Panics if `xs` or `ys` are empty or contain only zeros.
723//
724// This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are negative and
725// the result is written to the longer input slice.
726private_test_fn! {limbs_vec_and_neg_neg_in_place_either(
727 xs: &mut Vec<Limb>,
728 ys: &mut Vec<Limb>,
729) -> bool {
730 if xs.len() >= ys.len() {
731 limbs_vec_and_neg_neg_in_place_left(xs, ys);
732 false
733 } else {
734 limbs_vec_and_neg_neg_in_place_left(ys, xs);
735 true
736 }
737}}
738
739impl Natural {
740 fn and_assign_pos_limb_neg(&mut self, other: Limb) {
741 match self {
742 Self(Small(small)) => *small &= other,
743 Self(Large(limbs)) => limbs_pos_and_limb_neg_in_place(limbs, other),
744 }
745 }
746
747 fn and_pos_limb_neg(&self, other: Limb) -> Self {
748 Self(match self {
749 Self(Small(small)) => Small(small & other),
750 Self(Large(limbs)) => Large(limbs_pos_and_limb_neg(limbs, other)),
751 })
752 }
753
754 fn and_assign_neg_limb_neg(&mut self, other: Limb) {
755 match self {
756 &mut Self::ZERO => {}
757 Self(Small(small)) => {
758 let result = small.wrapping_neg() & other;
759 if result == 0 {
760 *self = Self(Large(vec![0, 1]));
761 } else {
762 *small = result.wrapping_neg();
763 }
764 }
765 Self(Large(limbs)) => limbs_vec_neg_and_limb_neg_in_place(limbs, other),
766 }
767 }
768
769 fn and_assign_pos_neg(&mut self, other: &Self) {
770 match (&mut *self, other) {
771 (_, Self(Small(y))) => self.and_assign_pos_limb_neg(y.wrapping_neg()),
772 (Self(Small(x)), Self(Large(ys))) => *x &= ys[0].wrapping_neg(),
773 (Self(Large(xs)), Self(Large(ys))) => {
774 limbs_and_pos_neg_in_place_left(xs, ys);
775 self.trim();
776 }
777 }
778 }
779
780 fn and_assign_neg_pos(&mut self, mut other: Self) {
781 other.and_assign_pos_neg(self);
782 *self = other;
783 }
784
785 fn and_assign_neg_pos_ref(&mut self, other: &Self) {
786 match (&mut *self, other) {
787 (Self(Small(x)), y) => *self = y.and_pos_limb_neg(x.wrapping_neg()),
788 (Self(Large(xs)), Self(Small(y))) => {
789 *self = Self(Small(xs[0].wrapping_neg() & *y));
790 }
791 (Self(Large(xs)), Self(Large(ys))) => {
792 limbs_vec_and_pos_neg_in_place_right(ys, xs);
793 self.trim();
794 }
795 }
796 }
797
798 fn and_pos_neg(&self, other: &Self) -> Self {
799 match (self, other) {
800 (_, &Self(Small(y))) => self.and_pos_limb_neg(y.wrapping_neg()),
801 (Self(Small(x)), Self(Large(ys))) => Self(Small(x & ys[0].wrapping_neg())),
802 (Self(Large(xs)), Self(Large(ys))) => {
803 Self::from_owned_limbs_asc(limbs_and_pos_neg(xs, ys))
804 }
805 }
806 }
807
808 fn and_neg_limb_neg(&self, other: Limb) -> Self {
809 Self(match self {
810 Self(Small(small)) => {
811 let result = small.wrapping_neg() & other;
812 if result == 0 {
813 Large(vec![0, 1])
814 } else {
815 Small(result.wrapping_neg())
816 }
817 }
818 Self(Large(limbs)) => Large(limbs_neg_and_limb_neg(limbs, other)),
819 })
820 }
821
822 fn and_assign_neg_neg(&mut self, mut other: Self) {
823 match (&mut *self, &mut other) {
824 (Self(Small(x)), _) => *self = other.and_neg_limb_neg(x.wrapping_neg()),
825 (_, Self(Small(y))) => self.and_assign_neg_limb_neg(y.wrapping_neg()),
826 (Self(Large(xs)), Self(Large(ys))) => {
827 if limbs_vec_and_neg_neg_in_place_either(xs, ys) {
828 *self = other;
829 }
830 self.trim();
831 }
832 }
833 }
834
835 fn and_assign_neg_neg_ref(&mut self, other: &Self) {
836 match (&mut *self, other) {
837 (Self(Small(x)), _) => *self = other.and_neg_limb_neg(x.wrapping_neg()),
838 (_, Self(Small(y))) => self.and_assign_neg_limb_neg(y.wrapping_neg()),
839 (Self(Large(xs)), Self(Large(ys))) => {
840 limbs_vec_and_neg_neg_in_place_left(xs, ys);
841 self.trim();
842 }
843 }
844 }
845
846 fn and_neg_neg(&self, other: &Self) -> Self {
847 match (self, other) {
848 (_, &Self(Small(y))) => self.and_neg_limb_neg(y.wrapping_neg()),
849 (&Self(Small(x)), _) => other.and_neg_limb_neg(x.wrapping_neg()),
850 (Self(Large(xs)), Self(Large(ys))) => {
851 Self::from_owned_limbs_asc(limbs_and_neg_neg(xs, ys))
852 }
853 }
854 }
855}
856
857impl BitAnd<Self> for Integer {
858 type Output = Self;
859
860 /// Takes the bitwise and of two [`Integer`]s, taking both by value.
861 ///
862 /// $$
863 /// f(x, y) = x \wedge y.
864 /// $$
865 ///
866 /// # Worst-case complexity
867 /// $T(n) = O(n)$
868 ///
869 /// $M(n) = O(1)$
870 ///
871 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
872 /// other.significant_bits())`.
873 ///
874 /// # Examples
875 /// ```
876 /// use malachite_base::num::arithmetic::traits::Pow;
877 /// use malachite_base::num::basic::traits::One;
878 /// use malachite_nz::integer::Integer;
879 ///
880 /// assert_eq!(Integer::from(-123) & Integer::from(-456), -512);
881 /// assert_eq!(
882 /// -Integer::from(10u32).pow(12) & -(Integer::from(10u32).pow(12) + Integer::ONE),
883 /// -1000000004096i64
884 /// );
885 /// ```
886 #[inline]
887 fn bitand(mut self, other: Self) -> Self {
888 self &= other;
889 self
890 }
891}
892
893impl BitAnd<&Self> for Integer {
894 type Output = Self;
895
896 /// Takes the bitwise and of two [`Integer`]s, taking the first by value and the second by
897 /// reference.
898 ///
899 /// $$
900 /// f(x, y) = x \wedge y.
901 /// $$
902 ///
903 /// # Worst-case complexity
904 /// $T(n) = O(n)$
905 ///
906 /// $M(m) = O(m)$
907 ///
908 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
909 /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
910 ///
911 /// # Examples
912 /// ```
913 /// use malachite_base::num::arithmetic::traits::Pow;
914 /// use malachite_base::num::basic::traits::One;
915 /// use malachite_nz::integer::Integer;
916 ///
917 /// assert_eq!(Integer::from(-123) & &Integer::from(-456), -512);
918 /// assert_eq!(
919 /// -Integer::from(10u32).pow(12) & &-(Integer::from(10u32).pow(12) + Integer::ONE),
920 /// -1000000004096i64
921 /// );
922 /// ```
923 #[inline]
924 fn bitand(mut self, other: &Self) -> Self {
925 self &= other;
926 self
927 }
928}
929
930impl BitAnd<Integer> for &Integer {
931 type Output = Integer;
932
933 /// Takes the bitwise and of two [`Integer`]s, taking the first by reference and the second by
934 /// value.
935 ///
936 /// $$
937 /// f(x, y) = x \wedge y.
938 /// $$
939 ///
940 /// # Worst-case complexity
941 /// $T(n) = O(n)$
942 ///
943 /// $M(m) = O(m)$
944 ///
945 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
946 /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
947 ///
948 /// # Examples
949 /// ```
950 /// use malachite_base::num::arithmetic::traits::Pow;
951 /// use malachite_base::num::basic::traits::One;
952 /// use malachite_nz::integer::Integer;
953 ///
954 /// assert_eq!(&Integer::from(-123) & Integer::from(-456), -512);
955 /// assert_eq!(
956 /// &-Integer::from(10u32).pow(12) & -(Integer::from(10u32).pow(12) + Integer::ONE),
957 /// -1000000004096i64
958 /// );
959 /// ```
960 #[inline]
961 fn bitand(self, mut other: Integer) -> Integer {
962 other &= self;
963 other
964 }
965}
966
967impl BitAnd<&Integer> for &Integer {
968 type Output = Integer;
969
970 /// Takes the bitwise and of two [`Integer`]s, taking both by reference.
971 ///
972 /// $$
973 /// f(x, y) = x \wedge y.
974 /// $$
975 ///
976 /// # Worst-case complexity
977 /// $T(n) = O(n)$
978 ///
979 /// $M(n) = O(n)$
980 ///
981 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
982 /// other.significant_bits())`.
983 ///
984 /// # Examples
985 /// ```
986 /// use malachite_base::num::arithmetic::traits::Pow;
987 /// use malachite_base::num::basic::traits::One;
988 /// use malachite_nz::integer::Integer;
989 ///
990 /// assert_eq!(&Integer::from(-123) & &Integer::from(-456), -512);
991 /// assert_eq!(
992 /// &-Integer::from(10u32).pow(12) & &-(Integer::from(10u32).pow(12) + Integer::ONE),
993 /// -1000000004096i64
994 /// );
995 /// ```
996 fn bitand(self, other: &Integer) -> Integer {
997 match (self.sign, other.sign) {
998 (true, true) => Integer {
999 sign: true,
1000 abs: &self.abs & &other.abs,
1001 },
1002 (true, false) => Integer {
1003 sign: true,
1004 abs: self.abs.and_pos_neg(&other.abs),
1005 },
1006 (false, true) => Integer {
1007 sign: true,
1008 abs: other.abs.and_pos_neg(&self.abs),
1009 },
1010 (false, false) => Integer {
1011 sign: false,
1012 abs: self.abs.and_neg_neg(&other.abs),
1013 },
1014 }
1015 }
1016}
1017
1018impl BitAndAssign<Self> for Integer {
1019 /// Bitwise-ands an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1020 /// right-hand side by value.
1021 ///
1022 /// $$
1023 /// x \gets x \wedge y.
1024 /// $$
1025 ///
1026 /// # Worst-case complexity
1027 /// $T(n) = O(n)$
1028 ///
1029 /// $M(n) = O(1)$
1030 ///
1031 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1032 /// other.significant_bits())`.
1033 ///
1034 /// # Examples
1035 /// ```
1036 /// use malachite_base::num::basic::traits::NegativeOne;
1037 /// use malachite_nz::integer::Integer;
1038 ///
1039 /// let mut x = Integer::NEGATIVE_ONE;
1040 /// x &= Integer::from(0x70ffffff);
1041 /// x &= Integer::from(0x7ff0_ffff);
1042 /// x &= Integer::from(0x7ffff0ff);
1043 /// x &= Integer::from(0x7ffffff0);
1044 /// assert_eq!(x, 0x70f0f0f0);
1045 /// ```
1046 fn bitand_assign(&mut self, other: Self) {
1047 match (self.sign, other.sign) {
1048 (true, true) => self.abs.bitand_assign(other.abs),
1049 (true, false) => self.abs.and_assign_pos_neg(&other.abs),
1050 (false, true) => {
1051 self.sign = true;
1052 self.abs.and_assign_neg_pos(other.abs);
1053 }
1054 (false, false) => self.abs.and_assign_neg_neg(other.abs),
1055 }
1056 }
1057}
1058
1059impl BitAndAssign<&Self> for Integer {
1060 /// Bitwise-ands an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1061 /// right-hand side by reference.
1062 ///
1063 /// $$
1064 /// x \gets x \wedge y.
1065 /// $$
1066 ///
1067 /// # Worst-case complexity
1068 /// $T(n) = O(n)$
1069 ///
1070 /// $M(m) = O(m)$
1071 ///
1072 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1073 /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1074 ///
1075 /// # Examples
1076 /// ```
1077 /// use malachite_base::num::basic::traits::NegativeOne;
1078 /// use malachite_nz::integer::Integer;
1079 ///
1080 /// let mut x = Integer::NEGATIVE_ONE;
1081 /// x &= &Integer::from(0x70ffffff);
1082 /// x &= &Integer::from(0x7ff0_ffff);
1083 /// x &= &Integer::from(0x7ffff0ff);
1084 /// x &= &Integer::from(0x7ffffff0);
1085 /// assert_eq!(x, 0x70f0f0f0);
1086 /// ```
1087 fn bitand_assign(&mut self, other: &Self) {
1088 match (self.sign, other.sign) {
1089 (true, true) => self.abs.bitand_assign(&other.abs),
1090 (true, false) => self.abs.and_assign_pos_neg(&other.abs),
1091 (false, true) => {
1092 self.sign = true;
1093 self.abs.and_assign_neg_pos_ref(&other.abs);
1094 }
1095 (false, false) => self.abs.and_assign_neg_neg_ref(&other.abs),
1096 }
1097 }
1098}