use crate::smith_waterman::backend::{Backend, ScoreVec};
#[allow(clippy::too_many_arguments)]
#[inline(always)]
unsafe fn unicode_gap_step<B: Backend, const SHIFT: i32>(
row: &mut B::Score,
pending_gap_open_mask: &mut B::Score,
adjacent_row: B::Score,
adjacent_pending_gap_open_mask: B::Score,
continuation_gap_extend_penalty: B::Score,
scalar_end_mask: B::Score,
total_gap_extend_penalty: B::Score,
gap_open_penalty: B::Score,
) {
unsafe {
let shifted_row = row.shift_right_padded::<SHIFT>(adjacent_row);
let shifted_pending_gap_open_mask =
pending_gap_open_mask.shift_right_padded::<SHIFT>(adjacent_pending_gap_open_mask);
let scalar_gap_extend_penalty =
total_gap_extend_penalty.subs(continuation_gap_extend_penalty);
let pending_gap_open_crossed_scalar_end =
shifted_pending_gap_open_mask.and(scalar_end_mask);
let gap_penalty = scalar_gap_extend_penalty
.add(gap_open_penalty.and(pending_gap_open_crossed_scalar_end));
let candidate_row = shifted_row.subs(gap_penalty);
*row = row.max(candidate_row);
let candidate_pending_gap_open_mask = shifted_pending_gap_open_mask.subs(scalar_end_mask);
*pending_gap_open_mask = pending_gap_open_mask.max(candidate_pending_gap_open_mask);
}
}
#[inline(always)]
unsafe fn prepare_next_unicode_gap_step<B: Backend, const SHIFT: i32>(
continuation_gap_extend_penalty: &mut B::Score,
adjacent_continuation_gap_extend_penalty: &mut B::Score,
scalar_end_mask: &mut B::Score,
adjacent_scalar_end_mask: &mut B::Score,
total_gap_extend_penalty: &mut B::Score,
) {
unsafe {
let zero = B::Score::zero();
let shifted_continuation_gap_extend_penalty = continuation_gap_extend_penalty
.shift_right_padded::<SHIFT>(*adjacent_continuation_gap_extend_penalty);
*continuation_gap_extend_penalty =
continuation_gap_extend_penalty.add(shifted_continuation_gap_extend_penalty);
*adjacent_continuation_gap_extend_penalty = adjacent_continuation_gap_extend_penalty
.add(adjacent_continuation_gap_extend_penalty.shift_right_padded::<SHIFT>(zero));
let shifted_scalar_end_mask =
scalar_end_mask.shift_right_padded::<SHIFT>(*adjacent_scalar_end_mask);
*scalar_end_mask = scalar_end_mask.max(shifted_scalar_end_mask);
*adjacent_scalar_end_mask = adjacent_scalar_end_mask
.max(adjacent_scalar_end_mask.shift_right_padded::<SHIFT>(zero));
*total_gap_extend_penalty = total_gap_extend_penalty.add(*total_gap_extend_penalty);
}
}
macro_rules! unicode_propagator {
($name:ident, [$($prepare_shift:literal),*], $final_shift:literal) => {
#[allow(clippy::too_many_arguments)]
#[inline(always)]
pub(crate) unsafe fn $name<B: Backend>(
row: B::Score,
adjacent_row: B::Score,
pending_gap_open_mask: B::Score,
adjacent_pending_gap_open_mask: B::Score,
continuation_gap_extend_penalty: B::Score,
adjacent_continuation_gap_extend_penalty: B::Score,
scalar_end_mask: B::Score,
adjacent_scalar_end_mask: B::Score,
gap_open_penalty: B::Score,
gap_extend_penalty: B::Score,
) -> (B::Score, B::Score) {
unsafe {
let mut row = row;
let mut pending_gap_open_mask = pending_gap_open_mask;
let mut continuation_gap_extend_penalty = continuation_gap_extend_penalty;
let mut adjacent_continuation_gap_extend_penalty =
adjacent_continuation_gap_extend_penalty;
let mut scalar_end_mask = scalar_end_mask;
let mut adjacent_scalar_end_mask = adjacent_scalar_end_mask;
let mut total_gap_extend_penalty = gap_extend_penalty;
$(
unicode_gap_step::<B, $prepare_shift>(
&mut row,
&mut pending_gap_open_mask,
adjacent_row,
adjacent_pending_gap_open_mask,
continuation_gap_extend_penalty,
scalar_end_mask,
total_gap_extend_penalty,
gap_open_penalty,
);
prepare_next_unicode_gap_step::<B, $prepare_shift>(
&mut continuation_gap_extend_penalty,
&mut adjacent_continuation_gap_extend_penalty,
&mut scalar_end_mask,
&mut adjacent_scalar_end_mask,
&mut total_gap_extend_penalty,
);
)*
unicode_gap_step::<B, $final_shift>(
&mut row,
&mut pending_gap_open_mask,
adjacent_row,
adjacent_pending_gap_open_mask,
continuation_gap_extend_penalty,
scalar_end_mask,
total_gap_extend_penalty,
gap_open_penalty,
);
(row, pending_gap_open_mask)
}
}
};
}
unicode_propagator!(propagate_unicode_8_lane, [1, 2], 4);
unicode_propagator!(propagate_unicode_16_lane, [1, 2, 4], 8);
#[cfg(target_arch = "x86_64")]
unicode_propagator!(propagate_unicode_32_lane, [1, 2, 4, 8], 16);
#[cfg(target_arch = "x86_64")]
unicode_propagator!(propagate_unicode_64_lane, [1, 2, 4, 8, 16], 32);