1use std::cmp::{max, min};
6use std::fmt;
7use std::hash::Hash;
8
9use crate::bits_to_base;
10use crate::kmer::{IntHelp, IntKmer};
11use crate::Kmer;
12use crate::Mer;
13use crate::Vmer;
14use serde_derive::{Deserialize, Serialize};
15
16fn block_set(kmer: u64, pos: usize, val: u8) -> u64 {
17 let offset = (31 - pos) * 2;
18 let mask = !(3 << offset);
19
20 (kmer & mask) | ((val as u64) << offset)
21}
22
23fn block_get(kmer: u64, pos: usize) -> u8 {
24 let offset = (31 - pos) * 2;
25 ((kmer >> offset) & 3) as u8
26}
27
28pub type Lmer1 = Lmer<[u64; 1]>;
29pub type Lmer2 = Lmer<[u64; 2]>;
30pub type Lmer3 = Lmer<[u64; 3]>;
31
32#[derive(Hash, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
35pub struct Lmer<A: Array> {
36 storage: A,
37}
38
39impl<A: Array<Item = u64> + Copy + Eq + Ord + Hash> Mer for Lmer<A> {
40 fn len(&self) -> usize {
42 (self.storage.as_slice()[A::size() - 1] & 0xff) as usize
43 }
44
45 fn is_empty(&self) -> bool {
46 self.len() == 0
47 }
48
49 fn get(&self, pos: usize) -> u8 {
51 let block = pos / 32;
52 let offset = pos % 32;
53 block_get(self.storage.as_slice()[block], offset)
54 }
55
56 fn set_mut(&mut self, pos: usize, val: u8) {
58 let block = pos / 32;
59 let offset = pos % 32;
60
61 let block_val = block_set(self.storage.as_slice()[block], offset, val);
62 self.storage.as_mut_slice()[block] = block_val;
63 }
64
65 fn set_slice_mut(&mut self, pos: usize, n_bases: usize, value: u64) {
66 let slc = self.storage.as_mut_slice();
67 let b0 = pos / 32;
68 let block_pos = pos % 32;
69 let top_mask = IntKmer::<u64>::top_mask(block_pos);
70 let mut bottom_mask =
71 IntKmer::<u64>::bottom_mask(max(0, 32usize.saturating_sub(block_pos + n_bases)));
72 if b0 == A::size() - 1 {
73 bottom_mask |= 0xFF
74 }
75 let mask = top_mask | bottom_mask;
76
77 let nb0 = 32 - block_pos;
78 let value_top = value >> (block_pos * 2);
79 let v0 = (slc[b0] & mask) | (value_top & !mask);
80 slc[b0] = v0;
81
82 if n_bases > nb0 {
83 let b1 = b0 + 1;
84 let nb1 = n_bases - nb0;
85 let bottom_mask = IntKmer::<u64>::bottom_mask(32 - nb1);
86 let value_bottom = value << (nb0 * 2);
87 let v1 = (slc[b1] & bottom_mask) | (value_bottom & !bottom_mask);
88 slc[b1] = v1
89 }
90 }
91
92 fn rc(&self) -> Self {
93 let slc = self.storage.as_slice();
94
95 let mut new_lmer = Self::new(self.len());
96 let mut block = 0;
97 let mut pos = 0;
98
99 while pos < self.len() {
100 let n_bases = min(32, self.len() - pos);
101
102 let mut v = slc[block];
103 if block == A::size() - 1 {
105 v &= !0xFF
106 }
107
108 let v_rc = !v.reverse_by_twos() << (64 - n_bases * 2);
109 new_lmer.set_slice_mut(self.len() - pos - n_bases, n_bases, v_rc);
110 block += 1;
111 pos += n_bases;
112 }
113
114 new_lmer
115 }
116}
117
118impl<A: Array<Item = u64> + Copy + Eq + Ord + Hash> Vmer for Lmer<A> {
119 fn max_len() -> usize {
120 (A::size() * 64 - 8) / 2
121 }
122
123 fn new(len: usize) -> Lmer<A> {
126 let mut arr = A::new();
127 {
128 let slc = arr.as_mut_slice();
129
130 slc[A::size() - 1] = (len as u64) & 0xff;
132 }
133 Lmer { storage: arr }
134 }
135
136 fn get_kmer<K: Kmer>(&self, pos: usize) -> K {
138 assert!(self.len() - pos >= K::k());
139 let slc = self.storage.as_slice();
140
141 let mut block = pos / 32;
143
144 let mut kmer_pos = 0;
146
147 let mut block_pos = pos % 32;
149
150 let mut kmer = K::empty();
151
152 while kmer_pos < K::k() {
153 let nb = min(K::k() - kmer_pos, 32 - block_pos);
155
156 let val = slc[block] << (2 * block_pos);
157 kmer.set_slice_mut(kmer_pos, nb, val);
158
159 block += 1;
161 kmer_pos += nb;
162 block_pos = 0;
164 }
165
166 kmer
167 }
168}
169
170impl<A: Array<Item = u64> + Copy + Eq + Ord + Hash> fmt::Debug for Lmer<A> {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 let mut s = String::new();
173 for pos in 0..self.len() {
174 s.push(bits_to_base(self.get(pos)))
175 }
176
177 write!(f, "{}", s)
178 }
179}
180
181pub trait Array {
183 type Item;
184 fn new() -> Self;
185 fn size() -> usize;
186
187 fn as_slice(&self) -> &[Self::Item];
188 fn as_mut_slice(&mut self) -> &mut [Self::Item];
189}
190
191macro_rules! impl_array(
192 ($($size:expr),+) => {
193 $(
194 impl<T: Default + Copy + Eq + Ord> Array for [T; $size] {
195 type Item = T;
196 fn new() -> [T; $size] { [T::default(); $size] }
197 fn size() -> usize { $size }
198 fn as_slice(&self) -> &[T] { self }
199 fn as_mut_slice(&mut self) -> &mut [T] { self }
200
201 }
202 )+
203 }
204);
205
206impl_array!(1, 2, 3, 4, 5, 6);