Skip to main content

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}