#![cfg_attr(feature = "low_mem", allow(dead_code))]
use serde::{Deserialize, Serialize};
use crate::align::traceback::TB_MAX;
use super::{SValue, TracebackCell};
#[derive(
Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize,
)]
pub struct PackedLengthCell {
s: u32,
i: u32,
d: u32,
aux: u32,
}
const TRACE_BIT_POS: u32 = 0;
const ALIGN_LEN_BIT_POS: u32 = 4;
const ALIGN_LEN_BIT_MASK: u32 = 0b0111_1111_1111_1111_1111_1111_1111;
const CONTIG_IDX_POS: u32 = 31;
const AUX_CONTIG_IDX_MASK: u32 = 0b1_1111;
const AUX_CONTIG_FROM_POS: u32 = 5;
impl PackedLengthCell {
#[inline(always)]
fn set_tb(&mut self, matrix: u32, tb: u16) -> u32 {
let bits: u32 = (0b1111) << TRACE_BIT_POS;
assert!(
tb <= TB_MAX,
"Expected a value <= TB_MAX while setting traceback bits"
);
(matrix & !bits) | ((tb as u32) << TRACE_BIT_POS) }
#[inline(always)]
fn set_len(&mut self, matrix: u32, len: u32) -> u32 {
let bits: u32 = ALIGN_LEN_BIT_MASK << ALIGN_LEN_BIT_POS;
(matrix & !bits) | (len << ALIGN_LEN_BIT_POS) }
#[inline(always)]
fn set_idx(&mut self, idx: u32) {
self.s = (self.s & !(1 << CONTIG_IDX_POS)) | (((idx >> 7) & 0b1) << CONTIG_IDX_POS);
self.i = (self.i & !(1 << CONTIG_IDX_POS)) | (((idx >> 6) & 0b1) << CONTIG_IDX_POS);
self.d = (self.d & !(1 << CONTIG_IDX_POS)) | (((idx >> 5) & 0b1) << CONTIG_IDX_POS);
self.aux = (self.aux & !AUX_CONTIG_IDX_MASK) | (idx & AUX_CONTIG_IDX_MASK);
}
#[inline(always)]
fn set_from(&mut self, from: u32) {
self.aux = (self.aux & AUX_CONTIG_IDX_MASK) | (from << AUX_CONTIG_FROM_POS)
}
#[inline(always)]
fn get_tb(self, matrix: u32) -> u16 {
((matrix >> TRACE_BIT_POS) & (0b1111)) as u16
}
#[inline(always)]
fn get_len(self, matrix: u32) -> u32 {
(matrix >> ALIGN_LEN_BIT_POS) & ALIGN_LEN_BIT_MASK
}
#[inline(always)]
fn get_idx(self) -> u32 {
let mut value = 0;
value |= (self.s >> 31) << 7;
value |= (self.i >> 31) << 6;
value |= (self.d >> 31) << 5;
value |= self.aux & AUX_CONTIG_IDX_MASK;
value
}
#[inline(always)]
fn get_from(self) -> u32 {
self.aux >> AUX_CONTIG_FROM_POS
}
}
impl TracebackCell for PackedLengthCell {
fn max_target_len() -> u32 {
134_217_727
}
fn max_num_contigs() -> u32 {
255
}
#[inline(always)]
fn set_i(&mut self, tb: u16, len: u32) {
self.i = self.set_tb(self.i, tb);
self.i = self.set_len(self.i, len);
}
#[inline(always)]
fn set_d(&mut self, tb: u16, len: u32) {
self.d = self.set_tb(self.d, tb);
self.d = self.set_len(self.d, len);
}
#[inline(always)]
fn set_s(&mut self, tb: u16, len: u32) {
self.s = self.set_tb(self.s, tb);
self.s = self.set_len(self.s, len);
}
#[inline(always)]
fn set_s_all(&mut self, tb: u16, len: u32, idx: u32, from: u32) {
assert!(idx <= Self::max_num_contigs());
assert!(from <= Self::max_target_len());
self.s = self.set_tb(self.s, tb);
self.s = self.set_len(self.s, len);
self.set_idx(idx);
self.set_from(from);
}
#[inline(always)]
fn get_i_len(self) -> u32 {
self.get_len(self.i)
}
#[inline(always)]
fn get_i(self) -> (u16, u32) {
(self.get_tb(self.i), self.get_len(self.i))
}
#[inline(always)]
fn get_d_len(self) -> u32 {
self.get_len(self.d)
}
#[inline(always)]
fn get_d(self) -> (u16, u32) {
(self.get_tb(self.d), self.get_len(self.d))
}
#[inline(always)]
fn get_s_len(self) -> u32 {
self.get_len(self.s)
}
#[inline(always)]
fn get_s(self) -> SValue {
SValue {
tb: self.get_tb(self.s),
len: self.get_s_len(),
idx: self.get_idx(),
from: self.get_from(),
}
}
}
#[cfg(test)]
pub mod tests {
use rstest::rstest;
use crate::align::traceback::{
packed_length_cell::PackedLengthCell, SValue, TracebackCell, TB_MAX,
};
#[rstest]
fn test_set_and_get_i() {
let mut cell = PackedLengthCell::default();
for tb in 0..=TB_MAX {
cell.set_i(0, 0);
assert_eq!(cell.get_i(), (0, 0));
assert_eq!(cell.get_i_len(), 0);
cell.set_i(tb, 13);
assert_eq!(cell.get_i(), (tb, 13));
assert_eq!(cell.get_i_len(), 13);
cell.set_i(0, 0);
}
}
#[rstest]
fn test_set_and_get_d() {
let mut cell = PackedLengthCell::default();
for tb in 0..=TB_MAX {
cell.set_d(0, 0);
assert_eq!(cell.get_d(), (0, 0));
assert_eq!(cell.get_d_len(), 0);
cell.set_d(tb, 13);
assert_eq!(cell.get_d(), (tb, 13));
assert_eq!(cell.get_d_len(), 13);
cell.set_d(0, 0);
}
}
#[rstest]
fn test_set_and_get_s() {
let mut cell = PackedLengthCell::default();
for tb in 0..=TB_MAX {
cell.set_s_all(0, 0, 0, 0);
assert_eq!(
cell.get_s(),
SValue {
tb: 0,
len: 0,
idx: 0,
from: 0
}
);
assert_eq!(cell.get_s_len(), 0);
cell.set_s(tb, 13);
assert_eq!(
cell.get_s(),
SValue {
tb,
len: 13,
idx: 0,
from: 0
}
);
assert_eq!(cell.get_s_len(), 13);
cell.set_s_all(tb, 14, 8, 22);
assert_eq!(
cell.get_s(),
SValue {
tb,
len: 14,
idx: 8,
from: 22
}
);
assert_eq!(cell.get_s_len(), 14);
}
}
}