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}