use crate::kernels::delta;
#[cfg(target_arch = "x86_64")]
use crate::{lcs_multiword_kernel, LargeCtx};
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "bmi1")]
#[allow(dead_code)]
#[inline]
pub(crate) unsafe fn myers_step(eq: u64, vp: u64, vn: u64) -> (u64, u64) {
myers_step_andn(eq, vp, vn)
}
#[inline(always)]
pub(crate) fn myers_step_andn(eq: u64, vp: u64, vn: u64) -> (u64, u64) {
let sum = (eq & vp).wrapping_add(vp);
let x = sum | (vp | eq);
let mh = vp & !(sum & !eq);
let xv = eq | vn;
let vns = vn << 1;
let xs = x << 1;
let m = xv | vns;
let s = !vns & xs;
let a = !m & xs;
((mh << 1) | a, !s & xv)
}
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "bmi1,popcnt,sse3,ssse3,sse4.1,sse4.2")]
pub(crate) unsafe fn multiword<const W: usize, I: Iterator<Item = [u64; W]>>(
m: usize,
pm_iter: I,
) -> isize {
multiword_andn::<W, I>(m, pm_iter)
}
#[cfg_attr(not(target_arch = "x86_64"), allow(dead_code))]
#[inline(always)]
pub(crate) fn multiword_andn<const W: usize, I: Iterator<Item = [u64; W]>>(
m: usize,
pm_iter: I,
) -> isize {
let mut vp = [!0u64; W];
let mut vn = [0u64; W];
for pm_row in pm_iter {
let (mut carry, mut prev_nhp, mut prev_hn) = (false, 0u64, 0u64);
for k in 0..W {
let (pm, v_p, v_n) = (pm_row[k], vp[k], vn[k]);
let x = pm | v_n;
let (sum, nc) = (x & v_p).carrying_add(v_p, carry);
carry = nc;
let d0 = (sum ^ v_p) | x;
let nhp = !v_n & (d0 | v_p);
let hn = v_p & d0;
let (nhp_s, hn_s) = (nhp << 1 | prev_nhp, hn << 1 | prev_hn);
vp[k] = hn_s | (!d0 & nhp_s);
vn[k] = !nhp_s & d0;
(prev_nhp, prev_hn) = (nhp >> 63, hn >> 63);
}
}
delta(vp, vn, m)
}
#[cfg(target_arch = "x86_64")]
const LCS_STRIP: usize = 4;
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "bmi1,popcnt,sse3,ssse3,sse4.1,sse4.2")]
pub(crate) unsafe fn lcs_full<F: Fn(usize) -> usize>(ctx: &LargeCtx<'_, F>) -> usize {
let mut carries = vec![0u8; ctx.n];
let mut lcs = 0;
for w0 in (0..ctx.w).step_by(LCS_STRIP) {
let c = Some(&mut carries[..]);
lcs += match ctx.w - w0 {
1 => lcs_multiword_kernel::<1, _>(ctx.rows::<1>(w0), c),
2 => lcs_multiword_kernel::<2, _>(ctx.rows::<2>(w0), c),
3 => lcs_multiword_kernel::<3, _>(ctx.rows::<3>(w0), c),
_ => lcs_multiword_kernel::<LCS_STRIP, _>(ctx.rows::<LCS_STRIP>(w0), c),
};
}
lcs
}