use crate::{
alignment::phmm::{
CorePhmm, DomainPhmm, GlobalPhmm, LocalPhmm, SemiLocalPhmm,
indexing::{GetCore, GetLayer},
modules::{PrecomputedDomainModule, PrecomputedLocalModule, SemiLocalModule},
},
data::views::IndexAdjustable,
};
use std::ops::{Bound, Range, RangeBounds, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
pub trait PhmmIndexRange: Clone {
type Start: PhmmIndex;
type End: PhmmIndex;
fn start_bound(&self) -> Bound<Self::Start>;
fn end_bound(&self) -> Bound<Self::End>;
}
impl<I: PhmmIndex, J: PhmmIndex> PhmmIndexRange for (Bound<I>, Bound<J>) {
type Start = I;
type End = J;
#[inline]
fn start_bound(&self) -> Bound<Self::Start> {
self.0
}
#[inline]
fn end_bound(&self) -> Bound<Self::End> {
self.1
}
}
impl<I: PhmmIndex> PhmmIndexRange for Range<I> {
type Start = I;
type End = I;
fn start_bound(&self) -> Bound<Self::Start> {
<Self as RangeBounds<I>>::start_bound(self).map(|x| *x)
}
fn end_bound(&self) -> Bound<Self::End> {
<Self as RangeBounds<I>>::end_bound(self).map(|x| *x)
}
}
impl<I: PhmmIndex> PhmmIndexRange for RangeInclusive<I> {
type Start = I;
type End = I;
fn start_bound(&self) -> Bound<Self::Start> {
<Self as RangeBounds<I>>::start_bound(self).map(|x| *x)
}
fn end_bound(&self) -> Bound<Self::End> {
<Self as RangeBounds<I>>::end_bound(self).map(|x| *x)
}
}
impl<I: PhmmIndex> PhmmIndexRange for RangeFrom<I> {
type Start = I;
type End = I;
fn start_bound(&self) -> Bound<Self::Start> {
<Self as RangeBounds<I>>::start_bound(self).map(|x| *x)
}
fn end_bound(&self) -> Bound<Self::End> {
<Self as RangeBounds<I>>::end_bound(self).map(|x| *x)
}
}
impl<I: PhmmIndex> PhmmIndexRange for RangeTo<I> {
type Start = I;
type End = I;
fn start_bound(&self) -> Bound<Self::Start> {
<Self as RangeBounds<I>>::start_bound(self).map(|x| *x)
}
fn end_bound(&self) -> Bound<Self::End> {
<Self as RangeBounds<I>>::end_bound(self).map(|x| *x)
}
}
impl<I: PhmmIndex> PhmmIndexRange for RangeToInclusive<I> {
type Start = I;
type End = I;
fn start_bound(&self) -> Bound<Self::Start> {
<Self as RangeBounds<I>>::start_bound(self).map(|x| *x)
}
fn end_bound(&self) -> Bound<Self::End> {
<Self as RangeBounds<I>>::end_bound(self).map(|x| *x)
}
}
pub trait PhmmIndexable: Sized {
#[must_use]
fn num_pseudomatch(&self) -> usize;
#[inline]
#[must_use]
fn seq_len(&self) -> usize {
self.num_pseudomatch() - 2
}
#[inline]
#[must_use]
fn get_dp_index(&self, j: impl PhmmIndex) -> usize {
j.get_phmm_dp_index(self)
}
#[inline]
#[must_use]
#[allow(dead_code)]
fn to_dp_index(&self, j: impl PhmmIndex) -> DpIndex {
DpIndex(self.get_dp_index(j))
}
#[inline]
#[must_use]
fn get_seq_index(&self, j: impl PhmmIndex) -> Option<usize> {
self.get_dp_index(j).checked_sub(1)
}
#[inline]
#[must_use]
fn to_seq_index(&self, j: impl PhmmIndex) -> Option<SeqIndex> {
self.get_seq_index(j).map(SeqIndex)
}
#[inline]
#[must_use]
fn get_dp_range<R: PhmmIndexRange>(&self, range: R) -> Range<usize> {
let start = match range.start_bound() {
Bound::Included(start) => self.get_dp_index(start),
Bound::Excluded(start) => self.get_dp_index(start) + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(end) => self.get_dp_index(end) + 1,
Bound::Excluded(end) => self.get_dp_index(end),
Bound::Unbounded => self.seq_len(),
};
start..end
}
#[inline]
#[must_use]
#[allow(dead_code)]
fn to_dp_range<R: PhmmIndexRange>(&self, range: R) -> Range<DpIndex> {
let Range { start, end } = self.get_dp_range(range);
DpIndex(start)..DpIndex(end)
}
#[inline]
#[must_use]
fn get_seq_range<R: PhmmIndexRange>(&self, range: R) -> Range<usize> {
self.get_dp_range(range).saturating_sub(1)
}
#[inline]
#[must_use]
#[allow(dead_code)]
fn to_seq_range<R: PhmmIndexRange>(&self, range: R) -> Range<SeqIndex> {
let Range { start, end } = self.get_seq_range(range);
SeqIndex(start)..SeqIndex(end)
}
}
pub trait QueryIndexable: Sized {
#[must_use]
fn seq_len(&self) -> usize;
#[inline]
#[must_use]
fn dp_len(&self) -> usize {
self.seq_len() + 1
}
#[inline]
#[must_use]
fn get_dp_index(&self, i: impl QueryIndex) -> usize {
i.get_query_dp_index(self)
}
#[inline]
#[must_use]
fn to_dp_index(&self, i: impl QueryIndex) -> DpIndex {
DpIndex(self.get_dp_index(i))
}
#[inline]
#[must_use]
fn get_dp_range(&self, start: Bound<impl QueryIndex>, end: Bound<impl QueryIndex>) -> Range<usize> {
let start = match start {
Bound::Included(start) => self.get_dp_index(start),
Bound::Excluded(start) => self.get_dp_index(start) + 1,
Bound::Unbounded => 0,
};
let end = match end {
Bound::Included(end) => self.get_dp_index(end) + 1,
Bound::Excluded(end) => self.get_dp_index(end),
Bound::Unbounded => self.seq_len(),
};
start..end
}
#[inline]
#[must_use]
fn get_seq_range(&self, start: Bound<impl QueryIndex>, end: Bound<impl QueryIndex>) -> Range<usize> {
self.get_dp_range(start, end).saturating_sub(1)
}
}
pub trait PhmmIndex: Copy {
#[must_use]
fn get_phmm_dp_index(self, v: &impl PhmmIndexable) -> usize;
#[inline]
#[must_use]
#[allow(dead_code)]
fn prev_index(self, phmm: &impl PhmmIndexable) -> DpIndex {
DpIndex(phmm.get_dp_index(self) - 1)
}
#[inline]
#[must_use]
fn next_index(self, phmm: &impl PhmmIndexable) -> DpIndex {
DpIndex(phmm.get_dp_index(self) + 1)
}
#[inline]
#[must_use]
#[allow(dead_code)]
fn min_index(self, other: impl PhmmIndex, phmm: &impl PhmmIndexable) -> DpIndex {
phmm.to_dp_index(self).min(phmm.to_dp_index(other))
}
#[inline]
#[must_use]
#[allow(dead_code)]
fn max_index(self, other: impl PhmmIndex, phmm: &impl PhmmIndexable) -> DpIndex {
phmm.to_dp_index(self).max(phmm.to_dp_index(other))
}
#[inline]
#[must_use]
#[allow(dead_code)]
fn eq_index(self, other: impl PhmmIndex, phmm: &impl PhmmIndexable) -> bool {
phmm.to_dp_index(self) == phmm.to_dp_index(other)
}
}
pub trait QueryIndex: Copy {
#[must_use]
fn get_query_dp_index(self, v: &impl QueryIndexable) -> usize;
}
#[repr(transparent)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct SeqIndex(pub usize);
#[repr(transparent)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct DpIndex(pub usize);
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Begin;
#[allow(dead_code)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct FirstMatch;
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct LastMatch;
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct End;
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
#[allow(dead_code)]
pub struct NoBases;
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
#[allow(dead_code)]
pub struct FirstBase;
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct LastBase;
impl<T, const S: usize> PhmmIndexable for CorePhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.layers().len() + 1
}
}
impl<T, const S: usize> PhmmIndexable for &CorePhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.layers().len() + 1
}
}
impl<T, const S: usize> PhmmIndexable for &mut CorePhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.layers().len() + 1
}
}
impl<T, const S: usize> PhmmIndexable for GlobalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &GlobalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &mut GlobalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for LocalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &LocalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &mut LocalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for SemiLocalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &SemiLocalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &mut SemiLocalPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for DomainPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &DomainPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &mut DomainPhmm<T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.core().num_pseudomatch()
}
}
impl<T> PhmmIndexable for SemiLocalModule<T> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.0.len()
}
}
impl<T> PhmmIndexable for &SemiLocalModule<T> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.0.len()
}
}
impl<T> PhmmIndexable for &mut SemiLocalModule<T> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.0.len()
}
}
impl<T, const S: usize> PhmmIndexable for PrecomputedLocalModule<'_, T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.semilocal_params.num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &PrecomputedLocalModule<'_, T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.semilocal_params.num_pseudomatch()
}
}
impl<T, const S: usize> PhmmIndexable for &mut PrecomputedLocalModule<'_, T, S> {
#[inline]
fn num_pseudomatch(&self) -> usize {
self.semilocal_params.num_pseudomatch()
}
}
impl QueryIndexable for &[u8] {
fn seq_len(&self) -> usize {
self.len()
}
}
impl<T, const S: usize> QueryIndexable for PrecomputedDomainModule<T, S> {
#[inline]
fn seq_len(&self) -> usize {
self.0.len() - 1
}
}
impl PhmmIndex for DpIndex {
#[inline]
fn get_phmm_dp_index(self, _v: &impl PhmmIndexable) -> usize {
self.0
}
}
impl PhmmIndex for SeqIndex {
#[inline]
fn get_phmm_dp_index(self, _v: &impl PhmmIndexable) -> usize {
self.0 + 1
}
}
impl PhmmIndex for Begin {
#[inline]
fn get_phmm_dp_index(self, _v: &impl PhmmIndexable) -> usize {
0
}
}
impl PhmmIndex for FirstMatch {
#[inline]
fn get_phmm_dp_index(self, _v: &impl PhmmIndexable) -> usize {
1
}
}
impl PhmmIndex for LastMatch {
#[inline]
fn get_phmm_dp_index(self, v: &impl PhmmIndexable) -> usize {
v.num_pseudomatch() - 2
}
}
impl PhmmIndex for End {
#[inline]
fn get_phmm_dp_index(self, v: &impl PhmmIndexable) -> usize {
v.num_pseudomatch() - 1
}
}
impl QueryIndex for NoBases {
#[inline]
fn get_query_dp_index(self, _v: &impl QueryIndexable) -> usize {
0
}
}
impl QueryIndex for FirstBase {
#[inline]
fn get_query_dp_index(self, _v: &impl QueryIndexable) -> usize {
1
}
}
impl QueryIndex for SeqIndex {
#[inline]
fn get_query_dp_index(self, _v: &impl QueryIndexable) -> usize {
self.0 + 1
}
}
impl QueryIndex for DpIndex {
#[inline]
fn get_query_dp_index(self, _v: &impl QueryIndexable) -> usize {
self.0
}
}
impl QueryIndex for LastBase {
#[inline]
fn get_query_dp_index(self, v: &impl QueryIndexable) -> usize {
v.dp_len() - 1
}
}