#[cfg(oxinum_simd)]
mod inner {
use core::simd::Simd;
const LANES: usize = 4;
pub(crate) fn and_limbs(a: &[u64], b: &[u64]) -> Vec<u64> {
let len = a.len().min(b.len());
let mut out: Vec<u64> = Vec::with_capacity(len);
let mut i = 0usize;
while i + LANES <= len {
let av = Simd::<u64, LANES>::from_slice(&a[i..]);
let bv = Simd::<u64, LANES>::from_slice(&b[i..]);
out.extend_from_slice(&(av & bv).to_array());
i += LANES;
}
while i < len {
out.push(a[i] & b[i]);
i += 1;
}
super::super::uint::normalize(&mut out);
out
}
pub(crate) fn or_limbs(a: &[u64], b: &[u64]) -> Vec<u64> {
let (short, long) = if a.len() <= b.len() { (a, b) } else { (b, a) };
let short_len = short.len();
let long_len = long.len();
let mut out: Vec<u64> = Vec::with_capacity(long_len);
let mut i = 0usize;
while i + LANES <= short_len {
let sv = Simd::<u64, LANES>::from_slice(&short[i..]);
let lv = Simd::<u64, LANES>::from_slice(&long[i..]);
out.extend_from_slice(&(sv | lv).to_array());
i += LANES;
}
while i < short_len {
out.push(short[i] | long[i]);
i += 1;
}
out.extend_from_slice(&long[short_len..]);
out
}
pub(crate) fn xor_limbs(a: &[u64], b: &[u64]) -> Vec<u64> {
let (short, long) = if a.len() <= b.len() { (a, b) } else { (b, a) };
let short_len = short.len();
let long_len = long.len();
let mut out: Vec<u64> = Vec::with_capacity(long_len);
let mut i = 0usize;
while i + LANES <= short_len {
let sv = Simd::<u64, LANES>::from_slice(&short[i..]);
let lv = Simd::<u64, LANES>::from_slice(&long[i..]);
out.extend_from_slice(&(sv ^ lv).to_array());
i += LANES;
}
while i < short_len {
out.push(short[i] ^ long[i]);
i += 1;
}
out.extend_from_slice(&long[short_len..]);
super::super::uint::normalize(&mut out);
out
}
pub(crate) fn shl_within(a: &[u64], s: u32) -> Vec<u64> {
debug_assert!((1..=63).contains(&s), "shl_within: s must be 1..=63");
let len = a.len();
let anti = 64u32 - s;
let mut out: Vec<u64> = Vec::with_capacity(len + 1);
out.push(a[0] << s);
let mut i = 1usize;
while i + LANES <= len {
let cur = Simd::<u64, LANES>::from_slice(&a[i..]);
let prev = Simd::<u64, LANES>::from_slice(&a[i - 1..]);
let shifted = (cur << Simd::splat(s as u64)) | (prev >> Simd::splat(anti as u64));
out.extend_from_slice(&shifted.to_array());
i += LANES;
}
while i < len {
out.push((a[i] << s) | (a[i - 1] >> anti));
i += 1;
}
let carry = a[len - 1] >> anti;
if carry != 0 {
out.push(carry);
}
super::super::uint::normalize(&mut out);
out
}
pub(crate) fn shr_within(a: &[u64], s: u32) -> Vec<u64> {
debug_assert!((1..=63).contains(&s), "shr_within: s must be 1..=63");
let len = a.len();
let anti = 64u32 - s;
let mut out: Vec<u64> = Vec::with_capacity(len);
let mut i = 0usize;
while i + LANES < len {
let cur = Simd::<u64, LANES>::from_slice(&a[i..]);
let next = Simd::<u64, LANES>::from_slice(&a[i + 1..]);
let shifted = (cur >> Simd::splat(s as u64)) | (next << Simd::splat(anti as u64));
out.extend_from_slice(&shifted.to_array());
i += LANES;
}
while i < len - 1 {
out.push((a[i] >> s) | (a[i + 1] << anti));
i += 1;
}
out.push(a[len - 1] >> s);
super::super::uint::normalize(&mut out);
out
}
}
#[cfg(not(oxinum_simd))]
mod inner {
pub(crate) fn and_limbs(a: &[u64], b: &[u64]) -> Vec<u64> {
let mut out: Vec<u64> = a.iter().zip(b.iter()).map(|(&x, &y)| x & y).collect();
super::super::uint::normalize(&mut out);
out
}
pub(crate) fn or_limbs(a: &[u64], b: &[u64]) -> Vec<u64> {
let (short, long) = if a.len() <= b.len() { (a, b) } else { (b, a) };
let mut out: Vec<u64> = short
.iter()
.zip(long.iter())
.map(|(&x, &y)| x | y)
.collect();
out.extend_from_slice(&long[short.len()..]);
out
}
pub(crate) fn xor_limbs(a: &[u64], b: &[u64]) -> Vec<u64> {
let (short, long) = if a.len() <= b.len() { (a, b) } else { (b, a) };
let mut out: Vec<u64> = short
.iter()
.zip(long.iter())
.map(|(&x, &y)| x ^ y)
.collect();
out.extend_from_slice(&long[short.len()..]);
super::super::uint::normalize(&mut out);
out
}
pub(crate) fn shl_within(a: &[u64], s: u32) -> Vec<u64> {
debug_assert!((1..=63).contains(&s), "shl_within: s must be 1..=63");
let anti = 64u32 - s;
let len = a.len();
let mut out: Vec<u64> = Vec::with_capacity(len + 1);
out.push(a[0] << s);
for i in 1..len {
out.push((a[i] << s) | (a[i - 1] >> anti));
}
let carry = a[len - 1] >> anti;
if carry != 0 {
out.push(carry);
}
super::super::uint::normalize(&mut out);
out
}
pub(crate) fn shr_within(a: &[u64], s: u32) -> Vec<u64> {
debug_assert!((1..=63).contains(&s), "shr_within: s must be 1..=63");
let anti = 64u32 - s;
let len = a.len();
let mut out: Vec<u64> = Vec::with_capacity(len);
for i in 0..len - 1 {
out.push((a[i] >> s) | (a[i + 1] << anti));
}
out.push(a[len - 1] >> s);
super::super::uint::normalize(&mut out);
out
}
}
pub(crate) use inner::{and_limbs, or_limbs, shl_within, shr_within, xor_limbs};