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