use crate::alphabet::ALPHABET_SIZE;
use crate::bwt::Bwt;
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct CArray {
pub data: [u32; ALPHABET_SIZE],
}
impl CArray {
pub fn from_text(text: &[u8]) -> Self {
let mut freq = [0u32; ALPHABET_SIZE];
for &ch in text {
if (ch as usize) < ALPHABET_SIZE {
freq[ch as usize] += 1;
}
}
let mut data = [0u32; ALPHABET_SIZE];
let mut sum = 0u32;
for i in 0..ALPHABET_SIZE {
data[i] = sum;
sum += freq[i];
}
Self { data }
}
pub fn from_bwt(bwt: &Bwt) -> Self {
let mut freq = [0u32; ALPHABET_SIZE];
for ch in bwt.iter_chars() {
if (ch as usize) < ALPHABET_SIZE {
freq[ch as usize] += 1;
}
}
let mut data = [0u32; ALPHABET_SIZE];
let mut sum = 0u32;
for i in 0..ALPHABET_SIZE {
data[i] = sum;
sum += freq[i];
}
Self { data }
}
pub fn get(&self, c: u8) -> u32 {
self.data[c as usize]
}
#[inline]
pub fn symbol_count(&self, c: u8, text_len: u32) -> u32 {
let next = (c as usize) + 1;
let upper = if next < ALPHABET_SIZE {
self.data[next]
} else {
text_len
};
upper - self.data[c as usize]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::alphabet::*;
#[test]
fn test_c_array_basic() {
let text = vec![A, C, G, T, SENTINEL];
let c = CArray::from_text(&text);
assert_eq!(c.data, [0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]);
}
#[test]
fn test_c_array_repeated() {
let text = vec![A, A, C, C, SENTINEL];
let c = CArray::from_text(&text);
assert_eq!(c.data, [0, 1, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]);
}
#[test]
fn test_c_array_empty() {
let text: Vec<u8> = vec![];
let c = CArray::from_text(&text);
assert_eq!(c.data, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
#[test]
fn test_c_array_with_n() {
let text = vec![A, N, N, SENTINEL];
let c = CArray::from_text(&text);
assert_eq!(c.data, [0, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);
}
#[test]
fn test_c_array_with_iupac() {
let text = vec![A, R, SENTINEL];
let c = CArray::from_text(&text);
assert_eq!(c.data[0], 0); assert_eq!(c.data[A as usize], 1);
assert_eq!(c.data[C as usize], 2); assert_eq!(c.data[N as usize], 2); assert_eq!(c.data[R as usize], 2); assert_eq!(c.data[Y as usize], 3); }
}