use super::{HeaplessBigInt, zero};
use crate::MachineWord;
use const_num_traits::Personality;
use core::marker::PhantomData;
use core::ops::{Shl, ShlAssign, Shr, ShrAssign};
impl<T: MachineWord, const CAP: usize, P: Personality> Shl<usize> for HeaplessBigInt<T, CAP, P> {
type Output = Self;
fn shl(self, bits: usize) -> Self::Output {
let word_bits = core::mem::size_of::<T>() * 8;
let word_shift = bits / word_bits;
let bit_shift = bits % word_bits;
let out_len = self.len as usize;
let mut limbs = [zero::<T>(); CAP];
let mut i = 0;
while i < out_len {
let dst_lo = i + word_shift;
if dst_lo < out_len {
let lo = self.limbs[i] << bit_shift;
limbs[dst_lo] |= lo;
if bit_shift > 0 {
let dst_hi = dst_lo + 1;
if dst_hi < out_len {
let hi = self.limbs[i] >> (word_bits - bit_shift);
limbs[dst_hi] |= hi;
}
}
}
i += 1;
}
Self {
limbs,
len: out_len as u16,
_p: PhantomData,
}
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> ShlAssign<usize>
for HeaplessBigInt<T, CAP, P>
{
fn shl_assign(&mut self, bits: usize) {
*self = *self << bits;
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> ShrAssign<usize>
for HeaplessBigInt<T, CAP, P>
{
fn shr_assign(&mut self, bits: usize) {
*self = *self >> bits;
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> Shr<usize> for HeaplessBigInt<T, CAP, P> {
type Output = Self;
fn shr(self, bits: usize) -> Self::Output {
let word_bits = core::mem::size_of::<T>() * 8;
let word_shift = bits / word_bits;
let bit_shift = bits % word_bits;
let mut limbs = [zero::<T>(); CAP];
if word_shift >= self.len as usize {
return Self {
limbs,
len: 0,
_p: PhantomData,
};
}
let out_len = self.len as usize - word_shift;
let mut i = 0;
while i < out_len {
let src_lo = i + word_shift;
let lo = self.limbs[src_lo] >> bit_shift;
let hi = if bit_shift > 0 && src_lo + 1 < self.len as usize {
self.limbs[src_lo + 1] << (word_bits - bit_shift)
} else {
zero::<T>()
};
limbs[i] = lo | hi;
i += 1;
}
Self {
limbs,
len: out_len as u16,
_p: PhantomData,
}
}
}