malachite_nz/integer/logic/
and.rs

1// Copyright © 2025 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.
40pub_test! {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`.
60pub_test! {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.
78pub_test! {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.
96pub_test! {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`.
117pub_test! {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.
151pub_test! {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.
180pub_test! {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(1)$
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.
202pub_test! {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.
254pub_test! {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.
304pub_test! {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.
348pub_test! {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(1)$
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.
391pub_test! {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.
435pub_test! {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.
507pub_test! {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.
587pub_test! {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.
648pub_test! {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.
697pub_test! {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.
726pub_test! {limbs_vec_and_neg_neg_in_place_either(xs: &mut Vec<Limb>, ys: &mut Vec<Limb>) -> bool {
727    if xs.len() >= ys.len() {
728        limbs_vec_and_neg_neg_in_place_left(xs, ys);
729        false
730    } else {
731        limbs_vec_and_neg_neg_in_place_left(ys, xs);
732        true
733    }
734}}
735
736impl Natural {
737    fn and_assign_pos_limb_neg(&mut self, other: Limb) {
738        match self {
739            Natural(Small(small)) => *small &= other,
740            Natural(Large(limbs)) => limbs_pos_and_limb_neg_in_place(limbs, other),
741        }
742    }
743
744    fn and_pos_limb_neg(&self, other: Limb) -> Natural {
745        Natural(match self {
746            Natural(Small(small)) => Small(small & other),
747            Natural(Large(limbs)) => Large(limbs_pos_and_limb_neg(limbs, other)),
748        })
749    }
750
751    fn and_assign_neg_limb_neg(&mut self, other: Limb) {
752        match self {
753            &mut Natural::ZERO => {}
754            Natural(Small(small)) => {
755                let result = small.wrapping_neg() & other;
756                if result == 0 {
757                    *self = Natural(Large(vec![0, 1]));
758                } else {
759                    *small = result.wrapping_neg();
760                }
761            }
762            Natural(Large(limbs)) => limbs_vec_neg_and_limb_neg_in_place(limbs, other),
763        }
764    }
765
766    fn and_assign_pos_neg(&mut self, other: &Natural) {
767        match (&mut *self, other) {
768            (_, Natural(Small(y))) => self.and_assign_pos_limb_neg(y.wrapping_neg()),
769            (Natural(Small(x)), Natural(Large(ys))) => *x &= ys[0].wrapping_neg(),
770            (Natural(Large(xs)), Natural(Large(ys))) => {
771                limbs_and_pos_neg_in_place_left(xs, ys);
772                self.trim();
773            }
774        }
775    }
776
777    fn and_assign_neg_pos(&mut self, mut other: Natural) {
778        other.and_assign_pos_neg(self);
779        *self = other;
780    }
781
782    fn and_assign_neg_pos_ref(&mut self, other: &Natural) {
783        match (&mut *self, other) {
784            (Natural(Small(x)), y) => *self = y.and_pos_limb_neg(x.wrapping_neg()),
785            (Natural(Large(xs)), Natural(Small(y))) => {
786                *self = Natural(Small(xs[0].wrapping_neg() & *y));
787            }
788            (Natural(Large(xs)), Natural(Large(ys))) => {
789                limbs_vec_and_pos_neg_in_place_right(ys, xs);
790                self.trim();
791            }
792        }
793    }
794
795    fn and_pos_neg(&self, other: &Natural) -> Natural {
796        match (self, other) {
797            (_, &Natural(Small(y))) => self.and_pos_limb_neg(y.wrapping_neg()),
798            (Natural(Small(x)), Natural(Large(ys))) => Natural(Small(x & ys[0].wrapping_neg())),
799            (Natural(Large(xs)), Natural(Large(ys))) => {
800                Natural::from_owned_limbs_asc(limbs_and_pos_neg(xs, ys))
801            }
802        }
803    }
804
805    fn and_neg_limb_neg(&self, other: Limb) -> Natural {
806        Natural(match self {
807            Natural(Small(small)) => {
808                let result = small.wrapping_neg() & other;
809                if result == 0 {
810                    Large(vec![0, 1])
811                } else {
812                    Small(result.wrapping_neg())
813                }
814            }
815            Natural(Large(limbs)) => Large(limbs_neg_and_limb_neg(limbs, other)),
816        })
817    }
818
819    fn and_assign_neg_neg(&mut self, mut other: Natural) {
820        match (&mut *self, &mut other) {
821            (Natural(Small(x)), _) => *self = other.and_neg_limb_neg(x.wrapping_neg()),
822            (_, Natural(Small(y))) => self.and_assign_neg_limb_neg(y.wrapping_neg()),
823            (Natural(Large(xs)), Natural(Large(ys))) => {
824                if limbs_vec_and_neg_neg_in_place_either(xs, ys) {
825                    *self = other;
826                }
827                self.trim();
828            }
829        }
830    }
831
832    fn and_assign_neg_neg_ref(&mut self, other: &Natural) {
833        match (&mut *self, other) {
834            (Natural(Small(x)), _) => *self = other.and_neg_limb_neg(x.wrapping_neg()),
835            (_, Natural(Small(y))) => self.and_assign_neg_limb_neg(y.wrapping_neg()),
836            (Natural(Large(xs)), Natural(Large(ys))) => {
837                limbs_vec_and_neg_neg_in_place_left(xs, ys);
838                self.trim();
839            }
840        }
841    }
842
843    fn and_neg_neg(&self, other: &Natural) -> Natural {
844        match (self, other) {
845            (_, &Natural(Small(y))) => self.and_neg_limb_neg(y.wrapping_neg()),
846            (&Natural(Small(x)), _) => other.and_neg_limb_neg(x.wrapping_neg()),
847            (Natural(Large(xs)), Natural(Large(ys))) => {
848                Natural::from_owned_limbs_asc(limbs_and_neg_neg(xs, ys))
849            }
850        }
851    }
852}
853
854impl BitAnd<Integer> for Integer {
855    type Output = Integer;
856
857    /// Takes the bitwise and of two [`Integer`]s, taking both by value.
858    ///
859    /// $$
860    /// f(x, y) = x \wedge y.
861    /// $$
862    ///
863    /// # Worst-case complexity
864    /// $T(n) = O(n)$
865    ///
866    /// $M(n) = O(1)$
867    ///
868    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
869    /// other.significant_bits())`.
870    ///
871    /// # Examples
872    /// ```
873    /// use malachite_base::num::arithmetic::traits::Pow;
874    /// use malachite_base::num::basic::traits::One;
875    /// use malachite_nz::integer::Integer;
876    ///
877    /// assert_eq!(Integer::from(-123) & Integer::from(-456), -512);
878    /// assert_eq!(
879    ///     -Integer::from(10u32).pow(12) & -(Integer::from(10u32).pow(12) + Integer::ONE),
880    ///     -1000000004096i64
881    /// );
882    /// ```
883    #[inline]
884    fn bitand(mut self, other: Integer) -> Integer {
885        self &= other;
886        self
887    }
888}
889
890impl BitAnd<&Integer> for Integer {
891    type Output = Integer;
892
893    /// Takes the bitwise and of two [`Integer`]s, taking the first by value and the second by
894    /// reference.
895    ///
896    /// $$
897    /// f(x, y) = x \wedge y.
898    /// $$
899    ///
900    /// # Worst-case complexity
901    /// $T(n) = O(n)$
902    ///
903    /// $M(m) = O(m)$
904    ///
905    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
906    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
907    ///
908    /// # Examples
909    /// ```
910    /// use malachite_base::num::arithmetic::traits::Pow;
911    /// use malachite_base::num::basic::traits::One;
912    /// use malachite_nz::integer::Integer;
913    ///
914    /// assert_eq!(Integer::from(-123) & &Integer::from(-456), -512);
915    /// assert_eq!(
916    ///     -Integer::from(10u32).pow(12) & &-(Integer::from(10u32).pow(12) + Integer::ONE),
917    ///     -1000000004096i64
918    /// );
919    /// ```
920    #[inline]
921    fn bitand(mut self, other: &Integer) -> Integer {
922        self &= other;
923        self
924    }
925}
926
927impl BitAnd<Integer> for &Integer {
928    type Output = Integer;
929
930    /// Takes the bitwise and of two [`Integer`]s, taking the first by reference and the seocnd by
931    /// value.
932    ///
933    /// $$
934    /// f(x, y) = x \wedge y.
935    /// $$
936    ///
937    /// # Worst-case complexity
938    /// $T(n) = O(n)$
939    ///
940    /// $M(m) = O(m)$
941    ///
942    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
943    /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
944    ///
945    /// # Examples
946    /// ```
947    /// use malachite_base::num::arithmetic::traits::Pow;
948    /// use malachite_base::num::basic::traits::One;
949    /// use malachite_nz::integer::Integer;
950    ///
951    /// assert_eq!(&Integer::from(-123) & Integer::from(-456), -512);
952    /// assert_eq!(
953    ///     &-Integer::from(10u32).pow(12) & -(Integer::from(10u32).pow(12) + Integer::ONE),
954    ///     -1000000004096i64
955    /// );
956    /// ```
957    #[inline]
958    fn bitand(self, mut other: Integer) -> Integer {
959        other &= self;
960        other
961    }
962}
963
964impl BitAnd<&Integer> for &Integer {
965    type Output = Integer;
966
967    /// Takes the bitwise and of two [`Integer`]s, taking both by reference.
968    ///
969    /// $$
970    /// f(x, y) = x \wedge y.
971    /// $$
972    ///
973    /// # Worst-case complexity
974    /// $T(n) = O(n)$
975    ///
976    /// $M(n) = O(n)$
977    ///
978    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
979    /// other.significant_bits())`.
980    ///
981    /// # Examples
982    /// ```
983    /// use malachite_base::num::arithmetic::traits::Pow;
984    /// use malachite_base::num::basic::traits::One;
985    /// use malachite_nz::integer::Integer;
986    ///
987    /// assert_eq!(&Integer::from(-123) & &Integer::from(-456), -512);
988    /// assert_eq!(
989    ///     &-Integer::from(10u32).pow(12) & &-(Integer::from(10u32).pow(12) + Integer::ONE),
990    ///     -1000000004096i64
991    /// );
992    /// ```
993    fn bitand(self, other: &Integer) -> Integer {
994        match (self.sign, other.sign) {
995            (true, true) => Integer {
996                sign: true,
997                abs: &self.abs & &other.abs,
998            },
999            (true, false) => Integer {
1000                sign: true,
1001                abs: self.abs.and_pos_neg(&other.abs),
1002            },
1003            (false, true) => Integer {
1004                sign: true,
1005                abs: other.abs.and_pos_neg(&self.abs),
1006            },
1007            (false, false) => Integer {
1008                sign: false,
1009                abs: self.abs.and_neg_neg(&other.abs),
1010            },
1011        }
1012    }
1013}
1014
1015impl BitAndAssign<Integer> for Integer {
1016    /// Bitwise-ands an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1017    /// right-hand side by value.
1018    ///
1019    /// $$
1020    /// x \gets x \wedge y.
1021    /// $$
1022    ///
1023    /// # Worst-case complexity
1024    /// $T(n) = O(n)$
1025    ///
1026    /// $M(n) = O(1)$
1027    ///
1028    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1029    /// other.significant_bits())`.
1030    ///
1031    /// # Examples
1032    /// ```
1033    /// use malachite_base::num::basic::traits::NegativeOne;
1034    /// use malachite_nz::integer::Integer;
1035    ///
1036    /// let mut x = Integer::NEGATIVE_ONE;
1037    /// x &= Integer::from(0x70ffffff);
1038    /// x &= Integer::from(0x7ff0_ffff);
1039    /// x &= Integer::from(0x7ffff0ff);
1040    /// x &= Integer::from(0x7ffffff0);
1041    /// assert_eq!(x, 0x70f0f0f0);
1042    /// ```
1043    fn bitand_assign(&mut self, other: Integer) {
1044        match (self.sign, other.sign) {
1045            (true, true) => self.abs.bitand_assign(other.abs),
1046            (true, false) => self.abs.and_assign_pos_neg(&other.abs),
1047            (false, true) => {
1048                self.sign = true;
1049                self.abs.and_assign_neg_pos(other.abs);
1050            }
1051            (false, false) => self.abs.and_assign_neg_neg(other.abs),
1052        }
1053    }
1054}
1055
1056impl BitAndAssign<&Integer> for Integer {
1057    /// Bitwise-ands an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1058    /// right-hand side by reference.
1059    ///
1060    /// $$
1061    /// x \gets x \wedge y.
1062    /// $$
1063    ///
1064    /// # Worst-case complexity
1065    /// $T(n) = O(n)$
1066    ///
1067    /// $M(m) = O(m)$
1068    ///
1069    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1070    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1071    ///
1072    /// # Examples
1073    /// ```
1074    /// use malachite_base::num::basic::traits::NegativeOne;
1075    /// use malachite_nz::integer::Integer;
1076    ///
1077    /// let mut x = Integer::NEGATIVE_ONE;
1078    /// x &= &Integer::from(0x70ffffff);
1079    /// x &= &Integer::from(0x7ff0_ffff);
1080    /// x &= &Integer::from(0x7ffff0ff);
1081    /// x &= &Integer::from(0x7ffffff0);
1082    /// assert_eq!(x, 0x70f0f0f0);
1083    /// ```
1084    fn bitand_assign(&mut self, other: &Integer) {
1085        match (self.sign, other.sign) {
1086            (true, true) => self.abs.bitand_assign(&other.abs),
1087            (true, false) => self.abs.and_assign_pos_neg(&other.abs),
1088            (false, true) => {
1089                self.sign = true;
1090                self.abs.and_assign_neg_pos_ref(&other.abs);
1091            }
1092            (false, false) => self.abs.and_assign_neg_neg_ref(&other.abs),
1093        }
1094    }
1095}