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}