use crate::natural::InnerNatural::{Large, Small};
use crate::natural::Natural;
use crate::platform::Limb;
use alloc::vec::Vec;
use core::cmp::Ordering::*;
use core::mem::swap;
use core::ops::{BitAnd, BitAndAssign};
use malachite_base::num::conversion::traits::WrappingFrom;
use malachite_base::slices::slice_set_zero;
pub_const_test! {limbs_and_limb(xs: &[Limb], y: Limb) -> Limb {
xs[0] & y
}}
pub_test! {limbs_and(xs: &[Limb], ys: &[Limb]) -> Vec<Limb> {
xs.iter().zip(ys.iter()).map(|(x, y)| x & y).collect()
}}
pub_test! {limbs_and_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
let len = xs.len();
assert_eq!(len, ys.len());
assert!(out.len() >= len);
for (out, (&x, &y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) {
*out = x & y;
}
}}
pub_test! {limbs_and_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) {
let xs_len = xs.len();
let ys_len = ys.len();
if xs_len >= ys_len {
assert!(out.len() >= xs_len);
limbs_and_same_length_to_out(out, &xs[..ys_len], ys);
slice_set_zero(&mut out[ys_len..xs_len]);
} else {
assert!(out.len() >= ys_len);
limbs_and_same_length_to_out(out, xs, &ys[..xs_len]);
slice_set_zero(&mut out[xs_len..ys_len]);
}
}}
pub_test! {limbs_slice_and_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) {
assert_eq!(xs.len(), ys.len());
for (x, &y) in xs.iter_mut().zip(ys.iter()) {
*x &= y;
}
}}
pub_test! {limbs_slice_and_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> Option<usize> {
let xs_len = xs.len();
let ys_len = ys.len();
match xs_len.cmp(&ys.len()) {
Equal => {
limbs_slice_and_same_length_in_place_left(xs, ys);
None
}
Greater => {
limbs_slice_and_same_length_in_place_left(&mut xs[..ys_len], ys);
Some(ys_len)
}
Less => {
limbs_slice_and_same_length_in_place_left(xs, &ys[..xs_len]);
None
}
}
}}
pub_test! {limbs_vec_and_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb]) {
if let Some(truncate_size) = limbs_slice_and_in_place_left(xs, ys) {
xs.truncate(truncate_size);
}
}}
pub_test! {limbs_and_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool {
let xs_len = xs.len();
let ys_len = ys.len();
match xs_len.cmp(&ys_len) {
Equal => {
limbs_slice_and_same_length_in_place_left(xs, ys);
false
}
Less => {
limbs_slice_and_same_length_in_place_left(xs, &ys[..xs_len]);
false
}
Greater => {
limbs_slice_and_same_length_in_place_left(ys, &xs[..ys_len]);
true
}
}
}}
impl Natural {
fn and_limb(self, other: Limb) -> Limb {
Limb::wrapping_from(&self) & other
}
fn and_limb_ref(&self, other: Limb) -> Limb {
Limb::wrapping_from(self) & other
}
fn and_assign_limb(&mut self, other: Limb) {
*self = Self(Small(self.and_limb_ref(other)));
}
}
impl BitAnd<Self> for Natural {
type Output = Self;
#[inline]
fn bitand(mut self, other: Self) -> Self {
self &= other;
self
}
}
impl<'a> BitAnd<&'a Self> for Natural {
type Output = Self;
#[inline]
fn bitand(mut self, other: &'a Self) -> Self {
self &= other;
self
}
}
impl BitAnd<Natural> for &Natural {
type Output = Natural;
#[inline]
fn bitand(self, mut other: Natural) -> Natural {
other &= self;
other
}
}
impl BitAnd<&Natural> for &Natural {
type Output = Natural;
fn bitand(self, other: &Natural) -> Natural {
match (self, other) {
(x, &Natural(Small(y))) => Natural(Small(x.and_limb_ref(y))),
(&Natural(Small(x)), y) => Natural(Small(y.and_limb_ref(x))),
(Natural(Large(xs)), Natural(Large(ys))) => {
Natural::from_owned_limbs_asc(limbs_and(xs, ys))
}
}
}
}
impl BitAndAssign<Self> for Natural {
fn bitand_assign(&mut self, mut other: Self) {
match (&mut *self, &mut other) {
(_, Self(Small(y))) => self.and_assign_limb(*y),
(Self(Small(x)), _) => *x = other.and_limb(*x),
(Self(Large(xs)), Self(Large(ys))) => {
if limbs_and_in_place_either(xs, ys) {
swap(xs, ys);
}
self.trim();
}
}
}
}
impl<'a> BitAndAssign<&'a Self> for Natural {
fn bitand_assign(&mut self, other: &'a Self) {
match (&mut *self, other) {
(_, Self(Small(y))) => self.and_assign_limb(*y),
(Self(Small(x)), _) => *x = other.and_limb_ref(*x),
(Self(Large(xs)), Self(Large(ys))) => {
limbs_vec_and_in_place_left(xs, ys);
self.trim();
}
}
}
}