Skip to main content

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}