malachite_nz/integer/logic/
or.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, 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.
39pub_test! {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`.
73pub_test! {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`, writes the limbs of the bitwise
96// or of the `Integer` and a `Limb` to the input slice. `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.
107pub_test! {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.
133pub_const_test! {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.
147pub_const_test! {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.
168pub_test! {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.
233pub_test! {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.
299pub_test! {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.
362pub_test! {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 = ys.to_vec();
377    } else {
378        let max_i = max(x_i, y_i);
379        match x_i.cmp(&y_i) {
380            Equal => {
381                xs[x_i] = (!xs[x_i] & (ys[y_i] - 1)) + 1;
382            }
383            Less => {
384                xs[x_i].wrapping_neg_assign();
385                limbs_not_in_place(&mut xs[x_i + 1..y_i]);
386                xs[y_i] = !xs[y_i] & (ys[y_i] - 1);
387            }
388            Greater => {
389                xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
390                xs[x_i] = !xs[x_i] & ys[x_i];
391            }
392        }
393        if xs_len < ys_len {
394            for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..xs_len].iter()) {
395                *x = !*x & y;
396            }
397            xs.extend_from_slice(&ys[xs_len..]);
398        } else {
399            for (x, y) in xs[max_i + 1..ys_len].iter_mut().zip(ys[max_i + 1..].iter()) {
400                *x = !*x & y;
401            }
402            xs.truncate(ys_len);
403        }
404    }
405}}
406
407// Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the
408// negative of another, writes the limbs of the bitwise or of the `Integer`s to the second (right)
409// slice. `xs` and `ys` may not be empty or only contain zeros.
410//
411// # Worst-case complexity
412// $T(n) = O(n)$
413//
414// $M(n) = O(1)$
415//
416// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
417//
418// # Panics
419// Panics if `xs` or `ys` are empty or contain only zeros.
420//
421// This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op2` and the first
422// input is positive and the second is negative.
423pub_test! {limbs_or_pos_neg_in_place_right(xs: &[Limb], ys: &mut [Limb]) {
424    let xs_len = xs.len();
425    let ys_len = ys.len();
426    let x_i = slice_leading_zeros(xs);
427    let y_i = slice_leading_zeros(ys);
428    assert!(x_i < xs_len);
429    assert!(y_i < ys_len);
430    if y_i >= xs_len {
431        ys[x_i] = xs[x_i].wrapping_neg();
432        limbs_not_to_out(&mut ys[x_i + 1..xs_len], &xs[x_i + 1..]);
433        for y in &mut ys[xs_len..y_i] {
434            *y = Limb::MAX;
435        }
436        ys[y_i] -= 1;
437    } else if x_i < ys_len {
438        let max_i = max(x_i, y_i);
439        match x_i.cmp(&y_i) {
440            Equal => {
441                ys[y_i] = (!xs[x_i] & (ys[y_i] - 1)) + 1;
442            }
443            Less => {
444                ys[x_i] = xs[x_i].wrapping_neg();
445                limbs_not_to_out(&mut ys[x_i + 1..y_i], &xs[x_i + 1..y_i]);
446                ys[y_i] = !xs[y_i] & (ys[y_i] - 1);
447            }
448            Greater => {
449                ys[x_i] &= !xs[x_i];
450            }
451        }
452        if xs_len < ys_len {
453            for (x, y) in xs[max_i + 1..].iter().zip(ys[max_i + 1..xs_len].iter_mut()) {
454                *y &= !x;
455            }
456        } else {
457            for (x, y) in xs[max_i + 1..ys_len].iter().zip(ys[max_i + 1..].iter_mut()) {
458                *y &= !x;
459            }
460        }
461    }
462}}
463
464// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
465// `Integer`s, returns the limbs of the bitwise or of the `Integer`s. `xs` and `ys` may not be empty
466// or only contain zeros.
467//
468// # Worst-case complexity
469// $T(n) = O(n)$
470//
471// $M(m) = O(m)$
472//
473// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is
474// `min(xs.len(), ys.len())`.
475//
476// # Panics
477// Panics if `xs` or `ys` are empty or contain only zeros.
478//
479// This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res` is returned and both
480// inputs are negative.
481pub_test! {limbs_or_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
482    let xs_len = xs.len();
483    let ys_len = ys.len();
484    let x_i = slice_leading_zeros(xs);
485    let y_i = slice_leading_zeros(ys);
486    assert!(x_i < xs_len);
487    assert!(y_i < ys_len);
488    if y_i >= xs_len {
489        xs.to_vec()
490    } else if x_i >= ys_len {
491        ys.to_vec()
492    } else {
493        let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
494        let mut out = vec![0; min_i];
495        let x = match x_i.cmp(&y_i) {
496            Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1,
497            Less => {
498                out.extend_from_slice(&xs[x_i..y_i]);
499                xs[y_i] & (ys[y_i] - 1)
500            }
501            Greater => {
502                out.extend_from_slice(&ys[y_i..x_i]);
503                (xs[x_i] - 1) & ys[x_i]
504            }
505        };
506        out.push(x);
507        out.extend(
508            xs[max_i + 1..]
509                .iter()
510                .zip(ys[max_i + 1..].iter())
511                .map(|(x, y)| x & y),
512        );
513        out
514    }
515}}
516
517// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
518// `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise or of the `Integer`s to
519// an output slice. `xs` and `ys` may not be empty or only contain zeros. The output slice must be
520// at least as long as the shorter input slice.
521//
522// # Worst-case complexity
523// $T(n) = O(n)$
524//
525// $M(n) = O(1)$
526//
527// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
528//
529// # Panics
530// Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the shorter
531// of `xs` and `ys`.
532//
533// This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where both inputs are negative.
534pub_test! {limbs_or_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
535    let xs_len = xs.len();
536    let ys_len = ys.len();
537    assert!(out.len() >= xs_len || out.len() >= ys_len);
538    let x_i = slice_leading_zeros(xs);
539    let y_i = slice_leading_zeros(ys);
540    assert!(x_i < xs_len);
541    assert!(y_i < ys_len);
542    if y_i >= xs_len {
543        out[..xs_len].copy_from_slice(xs);
544    } else if x_i >= ys_len {
545        out[..ys_len].copy_from_slice(ys);
546    } else {
547        let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) };
548        slice_set_zero(&mut out[..min_i]);
549        let x = match x_i.cmp(&y_i) {
550            Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1,
551            Less => {
552                out[x_i..y_i].copy_from_slice(&xs[x_i..y_i]);
553                xs[y_i] & (ys[y_i] - 1)
554            }
555            Greater => {
556                out[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
557                (xs[x_i] - 1) & ys[x_i]
558            }
559        };
560        out[max_i] = x;
561        for (out, (x, y)) in out[max_i + 1..]
562            .iter_mut()
563            .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()))
564        {
565            *out = x & y;
566        }
567    }
568}}
569
570// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
571// `Integer`s, writes the limbs of the bitwise or of the `Integer`s to the first (left) slice. `xs`
572// and `ys` may not be empty or only contain zeros. If the result has fewer significant limbs than
573// the left slice, the remaining limbs in the left slice are set to `Limb::MAX`.
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.
584//
585// This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1`, both inputs are
586// negative, and the length of `op1` is not changed.
587pub_test! {limbs_slice_or_neg_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) {
588    let xs_len = xs.len();
589    let ys_len = ys.len();
590    let x_i = slice_leading_zeros(xs);
591    let y_i = slice_leading_zeros(ys);
592    assert!(x_i < xs_len);
593    assert!(y_i < ys_len);
594    if y_i >= xs_len {
595    } else if x_i >= ys_len {
596        xs[..ys_len].copy_from_slice(ys);
597        slice_set_zero(&mut xs[ys_len..]);
598    } else {
599        let max_i = max(x_i, y_i);
600        if x_i > y_i {
601            xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
602        }
603        xs[max_i] = match x_i.cmp(&y_i) {
604            Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1,
605            Less => xs[y_i] & (ys[y_i] - 1),
606            Greater => (xs[x_i] - 1) & ys[x_i],
607        };
608        for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
609            *x &= y;
610        }
611        if xs_len > ys_len {
612            slice_set_zero(&mut xs[ys_len..]);
613        }
614    }
615}}
616
617// Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of the
618// negatives of two `Integer`s, writes the limbs of the bitwise or of the `Integer`s to the `Vec`.
619// `xs` and `ys` may not be empty or only contain zeros.
620//
621// # Worst-case complexity
622// $T(n) = O(n)$
623//
624// $M(n) = O(1)$
625//
626// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
627//
628// # Panics
629// Panics if `xs` or `ys` are empty or contain only zeros.
630//
631// This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1` and both inputs
632// are negative.
633pub_test! {limbs_vec_or_neg_neg_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
634    let xs_len = xs.len();
635    let ys_len = ys.len();
636    let x_i = slice_leading_zeros(xs);
637    let y_i = slice_leading_zeros(ys);
638    assert!(x_i < xs_len);
639    assert!(y_i < ys_len);
640    if y_i >= xs_len {
641    } else if x_i >= ys_len {
642        xs.truncate(ys_len);
643        xs.copy_from_slice(ys);
644    } else {
645        let max_i = max(x_i, y_i);
646        if x_i > y_i {
647            xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
648        }
649        xs[max_i] = match x_i.cmp(&y_i) {
650            Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1,
651            Less => xs[y_i] & (ys[y_i] - 1),
652            Greater => (xs[x_i] - 1) & ys[x_i],
653        };
654        for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
655            *x &= y;
656        }
657        xs.truncate(ys_len);
658    }
659}}
660
661// Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two
662// `Integer`s, writes the lower min(`xs.len()`, `ys.len()`) limbs of the bitwise or of the
663// `Integer`s to the shorter slice (or the first one, if they are equally long). `xs` and `ys` may
664// not be empty or only contain zeros. Returns a `bool` which is `false` when the output is to the
665// first slice and `true` when it's to the second slice.
666//
667// # Worst-case complexity
668// $T(n) = O(n)$
669//
670// $M(n) = O(1)$
671//
672// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
673//
674// # Panics
675// Panics if `xs` or `ys` are empty or contain only zeros.
676//
677// This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where both inputs are negative and
678// the result is written to the shorter input slice.
679pub_test! {limbs_or_neg_neg_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool {
680    let xs_len = xs.len();
681    let ys_len = ys.len();
682    let x_i = slice_leading_zeros(xs);
683    let y_i = slice_leading_zeros(ys);
684    assert!(x_i < xs_len);
685    assert!(y_i < ys_len);
686    if y_i >= xs_len {
687        false
688    } else if x_i >= ys_len {
689        true
690    } else {
691        let max_i = max(x_i, y_i);
692        let boundary = match x_i.cmp(&y_i) {
693            Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1,
694            Less => xs[y_i] & (ys[y_i] - 1),
695            Greater => (xs[x_i] - 1) & ys[x_i],
696        };
697        if xs_len > ys_len {
698            if y_i > x_i {
699                ys[x_i..y_i].copy_from_slice(&xs[x_i..y_i]);
700            }
701            ys[max_i] = boundary;
702            for (y, x) in ys[max_i + 1..].iter_mut().zip(xs[max_i + 1..].iter()) {
703                *y &= x;
704            }
705            true
706        } else {
707            if x_i > y_i {
708                xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]);
709            }
710            xs[max_i] = boundary;
711            for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) {
712                *x &= y;
713            }
714            false
715        }
716    }
717}}
718
719impl Natural {
720    fn or_assign_pos_limb_neg(&mut self, other: Limb) {
721        *self = self.or_pos_limb_neg(other);
722    }
723
724    fn or_pos_limb_neg(&self, other: Limb) -> Natural {
725        Natural(Small(match self {
726            Natural(Small(small)) => (small | other).wrapping_neg(),
727            Natural(Large(limbs)) => limbs_pos_or_neg_limb(limbs, other),
728        }))
729    }
730
731    fn or_assign_neg_limb_neg(&mut self, other: Limb) {
732        *self = self.or_neg_limb_neg(other);
733    }
734
735    #[allow(clippy::missing_const_for_fn)]
736    fn or_neg_limb_neg(&self, other: Limb) -> Natural {
737        Natural(Small(match self {
738            Natural(Small(small)) => (small.wrapping_neg() | other).wrapping_neg(),
739            Natural(Large(limbs)) => limbs_neg_or_neg_limb(limbs, other),
740        }))
741    }
742
743    fn or_assign_neg_limb_pos(&mut self, other: Limb) {
744        match self {
745            Natural(Small(small)) => {
746                *small = (small.wrapping_neg() | other).wrapping_neg();
747            }
748            Natural(Large(limbs)) => {
749                limbs_neg_or_limb_in_place(limbs, other);
750                self.trim();
751            }
752        }
753    }
754
755    fn or_neg_limb_pos(&self, other: Limb) -> Natural {
756        match self {
757            Natural(Small(small)) => Natural(Small((small.wrapping_neg() | other).wrapping_neg())),
758            Natural(Large(limbs)) => Natural::from_owned_limbs_asc(limbs_neg_or_limb(limbs, other)),
759        }
760    }
761
762    fn or_assign_pos_neg_ref(&mut self, other: &Natural) {
763        match (&mut *self, other) {
764            (_, Natural(Small(y))) => self.or_assign_pos_limb_neg(y.wrapping_neg()),
765            (Natural(Small(x)), _) => *self = other.or_neg_limb_pos(*x),
766            (Natural(Large(xs)), Natural(Large(ys))) => {
767                limbs_vec_or_pos_neg_in_place_left(xs, ys);
768                self.trim();
769            }
770        }
771    }
772
773    fn or_assign_pos_neg(&mut self, mut other: Natural) {
774        match (&mut *self, &mut other) {
775            (_, Natural(Small(y))) => self.or_assign_pos_limb_neg(y.wrapping_neg()),
776            (Natural(Small(x)), _) => {
777                other.or_assign_neg_limb_pos(*x);
778                *self = other;
779            }
780            (Natural(Large(xs)), Natural(Large(ys))) => {
781                limbs_or_pos_neg_in_place_right(xs, ys);
782                *self = other;
783                self.trim();
784            }
785        }
786    }
787
788    fn or_assign_neg_pos_ref(&mut self, other: &Natural) {
789        match (&mut *self, other) {
790            (_, Natural(Small(y))) => self.or_assign_neg_limb_pos(*y),
791            (Natural(Small(x)), _) => *self = other.or_pos_limb_neg(x.wrapping_neg()),
792            (Natural(Large(xs)), Natural(Large(ys))) => {
793                limbs_or_pos_neg_in_place_right(ys, xs);
794                self.trim();
795            }
796        }
797    }
798
799    fn or_assign_neg_pos(&mut self, mut other: Natural) {
800        match (&mut *self, &mut other) {
801            (_, Natural(Small(y))) => self.or_assign_neg_limb_pos(*y),
802            (Natural(Small(x)), _) => {
803                other.or_assign_pos_limb_neg(x.wrapping_neg());
804                *self = other;
805            }
806            (Natural(Large(xs)), Natural(Large(ys))) => {
807                limbs_or_pos_neg_in_place_right(ys, xs);
808                self.trim();
809            }
810        }
811    }
812
813    fn or_pos_neg(&self, other: &Natural) -> Natural {
814        match (self, other) {
815            (_, &Natural(Small(y))) => self.or_pos_limb_neg(y.wrapping_neg()),
816            (&Natural(Small(x)), _) => other.or_neg_limb_pos(x),
817            (Natural(Large(xs)), Natural(Large(ys))) => {
818                Natural::from_owned_limbs_asc(limbs_or_pos_neg(xs, ys))
819            }
820        }
821    }
822
823    fn or_assign_neg_neg_ref(&mut self, other: &Natural) {
824        match (&mut *self, other) {
825            (_, Natural(Small(y))) => self.or_assign_neg_limb_neg(y.wrapping_neg()),
826            (Natural(Small(x)), _) => *self = other.or_neg_limb_neg(x.wrapping_neg()),
827            (Natural(Large(xs)), Natural(Large(ys))) => {
828                limbs_vec_or_neg_neg_in_place_left(xs, ys);
829                self.trim();
830            }
831        }
832    }
833
834    fn or_assign_neg_neg(&mut self, mut other: Natural) {
835        match (&mut *self, &mut other) {
836            (_, Natural(Small(y))) => self.or_assign_neg_limb_neg(y.wrapping_neg()),
837            (Natural(Small(x)), _) => {
838                other.or_assign_neg_limb_neg(x.wrapping_neg());
839                *self = other;
840            }
841            (Natural(Large(xs)), Natural(Large(ys))) => {
842                if limbs_or_neg_neg_in_place_either(xs, ys) {
843                    *self = other;
844                }
845                self.trim();
846            }
847        }
848    }
849
850    fn or_neg_neg(&self, other: &Natural) -> Natural {
851        match (self, other) {
852            (_, &Natural(Small(y))) => self.or_neg_limb_neg(y.wrapping_neg()),
853            (&Natural(Small(x)), _) => other.or_neg_limb_neg(x.wrapping_neg()),
854            (Natural(Large(xs)), Natural(Large(ys))) => {
855                Natural::from_owned_limbs_asc(limbs_or_neg_neg(xs, ys))
856            }
857        }
858    }
859}
860
861impl BitOr<Integer> for Integer {
862    type Output = Integer;
863
864    /// Takes the bitwise or of two [`Integer`]s, taking both by value.
865    ///
866    /// $$
867    /// f(x, y) = x \vee y.
868    /// $$
869    ///
870    /// # Worst-case complexity
871    /// $T(n) = O(n)$
872    ///
873    /// $M(m) = O(m)$
874    ///
875    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
876    /// other.significant_bits())`, and $m$ is `min(self.significant_bits(),
877    /// other.significant_bits())`.
878    ///
879    /// # Examples
880    /// ```
881    /// use malachite_base::num::arithmetic::traits::Pow;
882    /// use malachite_base::num::basic::traits::One;
883    /// use malachite_nz::integer::Integer;
884    ///
885    /// assert_eq!(Integer::from(-123) | Integer::from(-456), -67);
886    /// assert_eq!(
887    ///     -Integer::from(10u32).pow(12) | -(Integer::from(10u32).pow(12) + Integer::ONE),
888    ///     -999999995905i64
889    /// );
890    /// ```
891    #[inline]
892    fn bitor(mut self, other: Integer) -> Integer {
893        self |= other;
894        self
895    }
896}
897
898impl<'a> BitOr<&'a Integer> for Integer {
899    type Output = Integer;
900
901    /// Takes the bitwise or of two [`Integer`]s, taking the first by value and the second by
902    /// reference.
903    ///
904    /// $$
905    /// f(x, y) = x \vee y.
906    /// $$
907    ///
908    /// # Worst-case complexity
909    /// $T(n) = O(n)$
910    ///
911    /// $M(m) = O(m)$
912    ///
913    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
914    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
915    ///
916    /// # Examples
917    /// ```
918    /// use malachite_base::num::arithmetic::traits::Pow;
919    /// use malachite_base::num::basic::traits::One;
920    /// use malachite_nz::integer::Integer;
921    ///
922    /// assert_eq!(Integer::from(-123) | &Integer::from(-456), -67);
923    /// assert_eq!(
924    ///     -Integer::from(10u32).pow(12) | &-(Integer::from(10u32).pow(12) + Integer::ONE),
925    ///     -999999995905i64
926    /// );
927    /// ```
928    #[inline]
929    fn bitor(mut self, other: &'a Integer) -> Integer {
930        self |= other;
931        self
932    }
933}
934
935impl BitOr<Integer> for &Integer {
936    type Output = Integer;
937
938    /// Takes the bitwise or of two [`Integer`]s, taking the first by reference and the second by
939    /// value.
940    ///
941    /// $$
942    /// f(x, y) = x \vee y.
943    /// $$
944    ///
945    /// # Worst-case complexity
946    /// $T(n) = O(n)$
947    ///
948    /// $M(m) = O(m)$
949    ///
950    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
951    /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
952    ///
953    /// # Examples
954    /// ```
955    /// use malachite_base::num::arithmetic::traits::Pow;
956    /// use malachite_base::num::basic::traits::One;
957    /// use malachite_nz::integer::Integer;
958    ///
959    /// assert_eq!(&Integer::from(-123) | Integer::from(-456), -67);
960    /// assert_eq!(
961    ///     &-Integer::from(10u32).pow(12) | -(Integer::from(10u32).pow(12) + Integer::ONE),
962    ///     -999999995905i64
963    /// );
964    /// ```
965    #[inline]
966    fn bitor(self, mut other: Integer) -> Integer {
967        other |= self;
968        other
969    }
970}
971
972impl BitOr<&Integer> for &Integer {
973    type Output = Integer;
974
975    /// Takes the bitwise or of two [`Integer`]s, taking both by reference.
976    ///
977    /// $$
978    /// f(x, y) = x \vee y.
979    /// $$
980    ///
981    /// # Worst-case complexity
982    /// $T(n) = O(n)$
983    ///
984    /// $M(n) = O(n)$
985    ///
986    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
987    /// other.significant_bits())`.
988    ///
989    /// # Examples
990    /// ```
991    /// use malachite_base::num::arithmetic::traits::Pow;
992    /// use malachite_base::num::basic::traits::One;
993    /// use malachite_nz::integer::Integer;
994    ///
995    /// assert_eq!(&Integer::from(-123) | &Integer::from(-456), -67);
996    /// assert_eq!(
997    ///     &-Integer::from(10u32).pow(12) | &-(Integer::from(10u32).pow(12) + Integer::ONE),
998    ///     -999999995905i64
999    /// );
1000    /// ```
1001    fn bitor(self, other: &Integer) -> Integer {
1002        match (self.sign, other.sign) {
1003            (true, true) => Integer {
1004                sign: true,
1005                abs: &self.abs | &other.abs,
1006            },
1007            (true, false) => Integer {
1008                sign: false,
1009                abs: self.abs.or_pos_neg(&other.abs),
1010            },
1011            (false, true) => Integer {
1012                sign: false,
1013                abs: other.abs.or_pos_neg(&self.abs),
1014            },
1015            (false, false) => Integer {
1016                sign: false,
1017                abs: self.abs.or_neg_neg(&other.abs),
1018            },
1019        }
1020    }
1021}
1022
1023impl BitOrAssign<Integer> for Integer {
1024    /// Bitwise-ors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1025    /// right-hand side by value.
1026    ///
1027    /// # Worst-case complexity
1028    /// $T(n) = O(n)$
1029    ///
1030    /// $M(m) = O(m)$
1031    ///
1032    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1033    /// other.significant_bits())`, and $m$ is `min(self.significant_bits(),
1034    /// other.significant_bits())`.
1035    ///
1036    /// # Examples
1037    /// ```
1038    /// use malachite_base::num::basic::traits::Zero;
1039    /// use malachite_nz::integer::Integer;
1040    ///
1041    /// let mut x = Integer::ZERO;
1042    /// x |= Integer::from(0x0000000f);
1043    /// x |= Integer::from(0x00000f00);
1044    /// x |= Integer::from(0x000f_0000);
1045    /// x |= Integer::from(0x0f000000);
1046    /// assert_eq!(x, 0x0f0f_0f0f);
1047    /// ```
1048    fn bitor_assign(&mut self, other: Integer) {
1049        match (self.sign, other.sign) {
1050            (true, true) => self.abs.bitor_assign(other.abs),
1051            (true, false) => {
1052                self.sign = false;
1053                self.abs.or_assign_pos_neg(other.abs);
1054            }
1055            (false, true) => self.abs.or_assign_neg_pos(other.abs),
1056            (false, false) => self.abs.or_assign_neg_neg(other.abs),
1057        }
1058    }
1059}
1060
1061impl<'a> BitOrAssign<&'a Integer> for Integer {
1062    /// Bitwise-ors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the
1063    /// right-hand side by reference.
1064    ///
1065    /// # Worst-case complexity
1066    /// $T(n) = O(n)$
1067    ///
1068    /// $M(m) = O(m)$
1069    ///
1070    /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1071    /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1072    ///
1073    /// # Examples
1074    /// ```
1075    /// use malachite_base::num::basic::traits::Zero;
1076    /// use malachite_nz::integer::Integer;
1077    ///
1078    /// let mut x = Integer::ZERO;
1079    /// x |= &Integer::from(0x0000000f);
1080    /// x |= &Integer::from(0x00000f00);
1081    /// x |= &Integer::from(0x000f_0000);
1082    /// x |= &Integer::from(0x0f000000);
1083    /// assert_eq!(x, 0x0f0f_0f0f);
1084    /// ```
1085    fn bitor_assign(&mut self, other: &'a Integer) {
1086        match (self.sign, other.sign) {
1087            (true, true) => self.abs.bitor_assign(&other.abs),
1088            (true, false) => {
1089                self.sign = false;
1090                self.abs.or_assign_pos_neg_ref(&other.abs);
1091            }
1092            (false, true) => self.abs.or_assign_neg_pos_ref(&other.abs),
1093            (false, false) => self.abs.or_assign_neg_neg_ref(&other.abs),
1094        }
1095    }
1096}