1use crate::lpf::lpf;
4use crate::sequence::Sequence;
5use crate::suffix_array::build as build_sa_lcp;
6use crate::NO_ALPHABET;
7
8#[derive(Clone, Debug)]
12pub struct LzArgs {
13 pub chunks: i32,
14 pub max_context: i32,
15 pub block_size: i32,
16 pub get_shuffle_terms: bool,
17 pub alphabet: u32,
18 pub log_base: u32,
19}
20
21impl LzArgs {
22 pub fn new() -> Self {
23 Self {
24 chunks: 0,
25 max_context: 0,
26 block_size: -1,
27 get_shuffle_terms: false,
28 alphabet: NO_ALPHABET,
29 log_base: NO_ALPHABET,
30 }
31 }
32}
33
34impl Default for LzArgs {
35 fn default() -> Self {
36 Self::new()
37 }
38}
39
40impl PartialEq for LzArgs {
41 fn eq(&self, other: &Self) -> bool {
42 self.chunks == other.chunks
43 && self.max_context == other.max_context
44 && self.block_size == other.block_size
45 && self.get_shuffle_terms == other.get_shuffle_terms
46 && self.alphabet == other.alphabet
47 }
48}
49
50#[derive(Clone, Debug, Default)]
52pub struct Lz76Result {
53 pub factorization: u32,
54 pub epsilon: f64,
55 pub lzf: Vec<u32>,
56}
57
58#[derive(Clone, Debug)]
60pub struct LzShuffle {
61 pub max_block_size: i32,
62 pub emc_value: f64,
63 pub multi_information: f64,
64 pub summands: Vec<f64>,
65}
66
67impl LzShuffle {
68 pub fn new(max_block_size: i32, emc_value: f64, multi_information: f64) -> Self {
69 Self {
70 max_block_size,
71 emc_value,
72 multi_information,
73 summands: Vec::new(),
74 }
75 }
76}
77
78impl Default for LzShuffle {
79 fn default() -> Self {
80 Self::new(-1, 0.0, 0.0)
81 }
82}
83
84#[derive(Clone, Debug, Default)]
86pub struct LzExtra {
87 pub lz_rajski_distance: f64,
88 pub redundancy: f64,
89 pub fh_uncertainty: f64,
90 pub lh_uncertainty: f64,
91 pub lz_pearson_coefficient: f64,
92}
93
94#[derive(Clone, Debug, Default)]
96pub struct LempelZiv {
97 pub complexity: u32,
98 pub entropy_density: f64,
99 pub random_shuffle_complexity: LzShuffle,
100 pub paired_shuffle_complexity: LzShuffle,
101 pub lz_normal_errors: f64,
102 pub lz_poison_errors: f64,
103 pub epsilon: f64,
104 pub factors_stddev: f64,
105 pub factors: Vec<u32>,
106 pub extras: LzExtra,
107}
108
109pub fn factorize(seq: &Sequence, args: &LzArgs) -> (u32, f64, Vec<u32>, f64) {
113 let n = seq.len();
114 if n == 0 {
115 return (0, 0.0, Vec::new(), 0.0);
116 }
117
118 let sa = build_sa_lcp(seq.as_bytes());
119 let log_base = if args.log_base == NO_ALPHABET {
120 seq.alphabet_size()
121 } else {
122 args.log_base
123 };
124 let alphabet = if args.alphabet == NO_ALPHABET {
125 seq.alphabet_size()
126 } else {
127 args.alphabet
128 };
129
130 let alphabet_f = alphabet.max(2) as f64;
131 let log_base_f = log_base.max(2) as f64;
132 let logn = log_base_f.ln();
133 let n_f = n as f64;
134 let epsilon = 2.0 * (1.0 + ((alphabet_f * n_f).ln() / logn).ln() / logn) / (n_f.ln() / logn);
135
136 let mut lpf_arr = vec![0u32; n];
137 lpf(&mut lpf_arr, sa.sa, sa.lcp, n);
140
141 let mut lzf: Vec<u32> = Vec::with_capacity(n);
142 lzf.push(0);
143 lzf.push(1);
144 let mut i: usize = 1;
145 while i < n {
146 let last = *lzf.last().unwrap() as usize;
147 let advance = lpf_arr.get(i).copied().unwrap_or(0) as usize;
148 i = last + advance + 1;
149 lzf.push(i as u32);
150 }
151
152 let factorization = if (*lzf.last().unwrap() as usize) <= n {
153 (lzf.len() - 1) as u32
154 } else {
155 (lzf.len() - 2) as u32
156 };
157
158 let stddev = factors_stddev(&lzf);
159 (factorization, epsilon, lzf, stddev)
160}
161
162fn factors_stddev(lzf: &[u32]) -> f64 {
163 if lzf.len() < 2 {
164 return 0.0;
165 }
166 let mean = (lzf[lzf.len() - 1] as f64 - 1.0) / lzf.len() as f64;
170 let mut max_factor_size = 0u32;
171 let mut sq_sum = 0.0;
172 for i in 1..lzf.len() {
173 let sz = lzf[i].saturating_sub(lzf[i - 1]);
174 if sz > max_factor_size {
175 max_factor_size = sz;
176 }
177 let diff = sz as f64 - mean;
178 sq_sum += diff * diff;
179 }
180 if max_factor_size == 0 {
181 0.0
182 } else {
183 (sq_sum / max_factor_size as f64).sqrt()
184 }
185}
186
187fn has_multiple_symbols(seq: &Sequence) -> bool {
190 let data = seq.as_bytes();
191 match data.first() {
192 None => false,
193 Some(&first) => data[1..].iter().any(|&b| b != first),
194 }
195}
196
197pub fn lz76_factorization(seq: &Sequence, args: &LzArgs) -> u32 {
199 if !has_multiple_symbols(seq) {
200 return 1;
201 }
202 let (c, _, _, _) = factorize(seq, args);
203 c
204}
205
206pub fn lz76_factors(seq: &Sequence, args: &LzArgs) -> Lz76Result {
208 if !has_multiple_symbols(seq) {
209 return Lz76Result {
210 factorization: 1,
211 epsilon: 0.0,
212 lzf: vec![0, 1, seq.len() as u32],
213 };
214 }
215 let (factorization, epsilon, lzf, _) = factorize(seq, args);
216 Lz76Result {
217 factorization,
218 epsilon,
219 lzf,
220 }
221}
222
223pub fn entropy_density_from(count: u32, seq: &Sequence, args: &LzArgs) -> f64 {
226 let log_base = if args.log_base == NO_ALPHABET {
227 seq.alphabet_size().max(2)
228 } else {
229 args.log_base.max(2)
230 } as f64;
231 let n = seq.len() as f64;
232 if n <= 1.0 {
233 return 0.0;
234 }
235 let div = n / (n.ln() / log_base.ln());
236 count as f64 / div
237}
238
239pub fn lz76_entropy_density(seq: &Sequence, args: &LzArgs) -> f64 {
241 entropy_density_from(lz76_factorization(seq, args), seq, args)
242}