1use crate::*;
2
3#[derive(Debug, Clone)]
4pub struct Log2Cache {
5 log2n: Vec<f64>,
6 nlog2n: Vec<f64>,
7 nlog2n_difference: Vec<f64>,
8}
9
10impl Log2Cache {
11 pub fn new(n: usize) -> Self {
12 let mut log2n = Vec::with_capacity(n + 1);
13 let mut nlog2n = Vec::with_capacity(n + 1);
14 let mut nlog2n_difference = Vec::with_capacity(n);
15 log2n.push(0.0);
16 nlog2n.push(0.0);
17 for i in 1..=n {
18 let i = i as f64;
19 let log2i = i.log2();
20 log2n.push(log2i);
21 let ilog2i = i * log2i;
22 let ilog2i_last = *nlog2n.last().unwrap();
23 nlog2n.push(ilog2i);
24 nlog2n_difference.push(ilog2i - ilog2i_last);
25 }
26 Self {
27 log2n,
28 nlog2n,
29 nlog2n_difference,
30 }
31 }
32
33 pub fn plog2p(&self, x: CountType, n: CountType) -> f64 {
34 let p = (x as f64) / (n as f64);
35 let log2p = unsafe {
36 *self.log2n.get_unchecked(x as usize) - *self.log2n.get_unchecked(n as usize)
37 };
38 p * log2p
39 }
40
41 pub fn nlog2n(&self, n: CountType) -> f64 {
42 unsafe { *self.nlog2n.get_unchecked(n as usize) }
43 }
44
45 pub fn nlog2n_difference(&self, n: CountType) -> f64 {
46 unsafe { *self.nlog2n_difference.get_unchecked(n as usize) }
47 }
48}