rustalign_fmindex/
params.rs1use std::mem::size_of;
7
8pub const OFF_SIZE: u32 = size_of::<u32>() as u32;
10
11const OFF_MASK: u64 = 0xFFFFFFFF;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct EbwtParams {
20 pub len: u64,
22
23 pub bwt_len: u64,
25
26 pub sz: u64,
28
29 pub bwt_sz: u64,
31
32 pub line_rate: i32,
34
35 pub orig_off_rate: i32,
37
38 pub off_rate: i32,
40
41 pub off_mask: u64,
43
44 pub ftab_chars: i32,
46
47 pub eftab_len: u32,
49
50 pub eftab_sz: u32,
52
53 pub ftab_len: u64,
55
56 pub ftab_sz: u64,
58
59 pub offs_len: u64,
61
62 pub offs_sz: u64,
64
65 pub line_sz: u32,
67
68 pub side_sz: u32,
70
71 pub side_bwt_sz: u32,
73
74 pub side_bwt_len: u32,
76
77 pub num_sides: u64,
79
80 pub num_lines: u64,
82
83 pub ebwt_tot_len: u64,
85
86 pub ebwt_tot_sz: u64,
88
89 pub color: bool,
91
92 pub entire_reverse: bool,
94}
95
96impl EbwtParams {
97 pub fn new(ref_len: u64) -> Self {
99 let line_rate = 6; let off_rate = 4; let ftab_chars = 8; Self::with_options(ref_len, line_rate, off_rate, ftab_chars, false, false)
105 }
106
107 pub fn with_options(
109 ref_len: u64,
110 line_rate: i32,
111 off_rate: i32,
112 ftab_chars: i32,
113 color: bool,
114 entire_reverse: bool,
115 ) -> Self {
116 let bwt_len = ref_len + 1; let sz = ref_len.div_ceil(4);
118 let bwt_sz = ref_len / 4 + 1;
119
120 let orig_off_rate = off_rate;
121 let off_mask = OFF_MASK << off_rate;
122
123 let eftab_len = (ftab_chars * 2) as u32;
124 let eftab_sz = eftab_len * OFF_SIZE;
125
126 let ftab_len = (1u64 << (ftab_chars * 2)) + 1;
127 let ftab_sz = ftab_len * OFF_SIZE as u64;
128
129 let offs_len = (bwt_len + (1u64 << off_rate) - 1) >> off_rate;
130 let offs_sz = offs_len * OFF_SIZE as u64;
131
132 let line_sz = 1u32 << line_rate;
133 let side_sz = line_sz; let side_bwt_sz = side_sz - OFF_SIZE * 4;
135 let side_bwt_len = side_bwt_sz * 4;
136
137 let num_sides = bwt_sz.div_ceil(side_bwt_sz as u64);
138 let num_lines = num_sides; let ebwt_tot_len = num_sides * side_sz as u64;
141 let ebwt_tot_sz = ebwt_tot_len;
142
143 Self {
144 len: ref_len,
145 bwt_len,
146 sz,
147 bwt_sz,
148 line_rate,
149 orig_off_rate,
150 off_rate,
151 off_mask,
152 ftab_chars,
153 eftab_len,
154 eftab_sz,
155 ftab_len,
156 ftab_sz,
157 offs_len,
158 offs_sz,
159 line_sz,
160 side_sz,
161 side_bwt_sz,
162 side_bwt_len,
163 num_sides,
164 num_lines,
165 ebwt_tot_len,
166 ebwt_tot_sz,
167 color,
168 entire_reverse,
169 }
170 }
171
172 pub fn set_off_rate(&mut self, off_rate: i32) {
174 self.off_rate = off_rate;
175 self.off_mask = OFF_MASK << off_rate;
176 self.offs_len = (self.bwt_len + (1u64 << off_rate) - 1) >> off_rate;
177 self.offs_sz = self.offs_len * OFF_SIZE as u64;
178 }
179
180 pub fn side_size(&self) -> u32 {
182 self.side_sz
183 }
184
185 pub fn pos_to_side(&self, pos: u64) -> u64 {
187 pos / (self.side_bwt_len as u64)
188 }
189
190 #[allow(clippy::manual_is_multiple_of)]
192 pub fn is_valid(&self) -> bool {
193 self.len > 0
194 && self.line_rate > 3
195 && self.off_rate >= 0
196 && self.ftab_chars <= 16
197 && self.ftab_chars >= 1
198 && self.line_rate < 32
199 && self.ftab_chars < 32
200 && self.ebwt_tot_sz % (self.line_sz as u64) == 0
201 }
202
203 pub fn total_size(&self) -> u64 {
205 self.ebwt_tot_sz + self.ftab_sz + self.eftab_sz as u64 + self.offs_sz
207 }
208}
209
210impl Default for EbwtParams {
211 fn default() -> Self {
212 Self::new(0)
213 }
214}
215
216impl EbwtParams {
217 #[cfg(test)]
219 pub fn new_test_params(bwt_len: usize) -> Self {
220 Self::new(bwt_len as u64 - 1)
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_params_new() {
230 let params = EbwtParams::new(1000);
231 assert_eq!(params.len, 1000);
232 assert_eq!(params.bwt_len, 1001);
233 assert!(params.is_valid());
234 }
235
236 #[test]
237 fn test_params_with_options() {
238 let params = EbwtParams::with_options(5000, 5, 3, 6, false, false);
239 assert_eq!(params.len, 5000);
240 assert_eq!(params.bwt_len, 5001);
241 assert_eq!(params.line_rate, 5);
242 assert_eq!(params.off_rate, 3);
243 assert!(params.is_valid());
244 }
245
246 #[test]
247 fn test_set_off_rate() {
248 let mut params = EbwtParams::new(10000);
249 let orig_offs_len = params.offs_len;
250 params.set_off_rate(5);
251 assert_eq!(params.off_rate, 5);
252 assert_ne!(params.offs_len, orig_offs_len);
253 }
254
255 #[test]
256 fn test_pos_to_side() {
257 let params = EbwtParams::with_options(10000, 6, 4, 8, false, false);
258 let side = params.pos_to_side(100);
263 assert_eq!(side, 100 / params.side_bwt_len as u64);
264 }
265
266 #[test]
267 fn test_sizes() {
268 let params = EbwtParams::new(1000);
269 assert!(params.sz > 0);
270 assert!(params.bwt_sz > 0);
271 assert!(params.side_sz > 0);
272 }
273}