use super::{HeaplessBigInt, zero};
use crate::MachineWord;
use const_num_traits::Personality;
use core::marker::PhantomData;
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
macro_rules! forward_bitwise_receivers {
($imp:ident, $method:ident) => {
impl<T: MachineWord, const CAP: usize, P: Personality> $imp for HeaplessBigInt<T, CAP, P> {
type Output = Self;
fn $method(self, other: Self) -> Self {
(&self).$method(&other)
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> $imp<&HeaplessBigInt<T, CAP, P>>
for HeaplessBigInt<T, CAP, P>
{
type Output = Self;
fn $method(self, other: &Self) -> Self {
(&self).$method(other)
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> $imp<HeaplessBigInt<T, CAP, P>>
for &HeaplessBigInt<T, CAP, P>
{
type Output = HeaplessBigInt<T, CAP, P>;
fn $method(self, other: HeaplessBigInt<T, CAP, P>) -> HeaplessBigInt<T, CAP, P> {
self.$method(&other)
}
}
};
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitAnd<&HeaplessBigInt<T, CAP, P>>
for &HeaplessBigInt<T, CAP, P>
{
type Output = HeaplessBigInt<T, CAP, P>;
fn bitand(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
let out_len = core::cmp::max(self.len, other.len);
let n = out_len as usize;
let mut limbs = [zero::<T>(); CAP];
for ((&ai, &bi), oi) in self.limbs[..n]
.iter()
.zip(&other.limbs[..n])
.zip(&mut limbs[..n])
{
*oi = ai & bi;
}
HeaplessBigInt {
limbs,
len: out_len,
_p: PhantomData,
}
}
}
forward_bitwise_receivers!(BitAnd, bitand);
impl<T: MachineWord, const CAP: usize, P: Personality> BitOr<&HeaplessBigInt<T, CAP, P>>
for &HeaplessBigInt<T, CAP, P>
{
type Output = HeaplessBigInt<T, CAP, P>;
fn bitor(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
let out_len = core::cmp::max(self.len, other.len);
let n = out_len as usize;
let mut limbs = [zero::<T>(); CAP];
for ((&ai, &bi), oi) in self.limbs[..n]
.iter()
.zip(&other.limbs[..n])
.zip(&mut limbs[..n])
{
*oi = ai | bi;
}
HeaplessBigInt {
limbs,
len: out_len,
_p: PhantomData,
}
}
}
forward_bitwise_receivers!(BitOr, bitor);
impl<T: MachineWord, const CAP: usize, P: Personality> BitXor<&HeaplessBigInt<T, CAP, P>>
for &HeaplessBigInt<T, CAP, P>
{
type Output = HeaplessBigInt<T, CAP, P>;
fn bitxor(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
let out_len = core::cmp::max(self.len, other.len);
let n = out_len as usize;
let mut limbs = [zero::<T>(); CAP];
for ((&ai, &bi), oi) in self.limbs[..n]
.iter()
.zip(&other.limbs[..n])
.zip(&mut limbs[..n])
{
*oi = ai ^ bi;
}
HeaplessBigInt {
limbs,
len: out_len,
_p: PhantomData,
}
}
}
forward_bitwise_receivers!(BitXor, bitxor);
impl<T: MachineWord, const CAP: usize, P: Personality> Not for HeaplessBigInt<T, CAP, P> {
type Output = Self;
fn not(self) -> Self {
let n = self.len as usize;
let mut limbs = [zero::<T>(); CAP];
for (o, &s) in limbs[..n].iter_mut().zip(&self.limbs[..n]) {
*o = !s;
}
HeaplessBigInt {
limbs,
len: self.len,
_p: PhantomData,
}
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> Not for &HeaplessBigInt<T, CAP, P> {
type Output = HeaplessBigInt<T, CAP, P>;
fn not(self) -> Self::Output {
!*self
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitAndAssign for HeaplessBigInt<T, CAP, P> {
fn bitand_assign(&mut self, other: Self) {
self.bitand_assign(&other);
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitAndAssign<&HeaplessBigInt<T, CAP, P>>
for HeaplessBigInt<T, CAP, P>
{
fn bitand_assign(&mut self, other: &Self) {
let min_len = core::cmp::min(self.len, other.len) as usize;
let self_len = self.len as usize;
let max_len = core::cmp::max(self.len, other.len);
for (si, &oi) in self.limbs[..min_len]
.iter_mut()
.zip(&other.limbs[..min_len])
{
*si &= oi;
}
for si in &mut self.limbs[min_len..self_len] {
*si = zero::<T>();
}
self.len = max_len;
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitOrAssign for HeaplessBigInt<T, CAP, P> {
fn bitor_assign(&mut self, other: Self) {
self.bitor_assign(&other);
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitOrAssign<&HeaplessBigInt<T, CAP, P>>
for HeaplessBigInt<T, CAP, P>
{
fn bitor_assign(&mut self, other: &Self) {
let self_len = self.len as usize;
let max_len = core::cmp::max(self_len, other.len as usize);
for (si, &oi) in self.limbs[..self_len]
.iter_mut()
.zip(&other.limbs[..self_len])
{
*si |= oi;
}
for (si, &oi) in self.limbs[self_len..max_len]
.iter_mut()
.zip(&other.limbs[self_len..max_len])
{
*si = oi;
}
self.len = max_len as u16;
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitXorAssign for HeaplessBigInt<T, CAP, P> {
fn bitxor_assign(&mut self, other: Self) {
self.bitxor_assign(&other);
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> BitXorAssign<&HeaplessBigInt<T, CAP, P>>
for HeaplessBigInt<T, CAP, P>
{
fn bitxor_assign(&mut self, other: &Self) {
let self_len = self.len as usize;
let max_len = core::cmp::max(self_len, other.len as usize);
for (si, &oi) in self.limbs[..self_len]
.iter_mut()
.zip(&other.limbs[..self_len])
{
*si ^= oi;
}
for (si, &oi) in self.limbs[self_len..max_len]
.iter_mut()
.zip(&other.limbs[self_len..max_len])
{
*si = oi;
}
self.len = max_len as u16;
}
}