use core::arch::aarch64::*;
use core::mem;
pub(crate) fn bignum_aff_point_select_p384(z: &mut [u64; 12], table: &[u64], index: u8) {
select::<12, 6>(z, table, index)
}
pub(crate) fn bignum_aff_point_select_p521(z: &mut [u64; 18], table: &[u64], index: u8) {
select::<18, 9>(z, table, index)
}
fn select<const N: usize, const V: usize>(z: &mut [u64; N], table: &[u64], index: u8) {
const { assert!(N == 2 * V) };
unsafe { _select::<N, V>(z, table, index) }
}
#[target_feature(enable = "neon")]
fn _select<const N: usize, const V: usize>(z: &mut [u64; N], table: &[u64], index: u8) {
let mut acc: [uint32x4_t; V] = [unsafe { mem::transmute::<u128, uint32x4_t>(0) }; V];
let desired_index = vdupq_n_u32(index as u32);
let ones = vdupq_n_u32(1);
let mut index = ones;
let (rows, _) = table.as_chunks::<N>();
for row in rows {
let mask = vceqq_u32(index, desired_index);
index = vaddq_u32(index, ones);
for (i, acc) in acc.iter_mut().enumerate() {
let word = unsafe { vld1q_u32(row.as_ptr().add(2 * i).cast()) };
*acc = veorq_u32(*acc, vandq_u32(word, mask));
}
}
for (i, acc) in acc.iter().enumerate() {
unsafe { vst1q_u32(z.as_mut_ptr().add(2 * i).cast(), *acc) };
}
}