1use super::super::alloc;
2use super::super::alloc::{SliceWrapper, SliceWrapperMut};
3use super::input_pair::{InputPair, InputReference};
4use super::interface;
5use super::util::FastLog2;
6use core::cmp;
7
8use core::ops::{Index, IndexMut, Range};
9pub type floatY = f64;
11pub fn HuffmanCost(population: &[u32]) -> floatY {
14 assert_eq!(population.len(), 256 * 256);
15 let mut cost: floatY = 0.0 as floatY;
16 let mut sum: floatY = 0.0 as floatY;
17 let mut buckets: floatY = 0.0 as floatY;
18 for pop in population.iter() {
19 if *pop == 0 {
20 continue;
21 }
22 cost -= *pop as floatY * FastLog2(*pop as u64) as floatY;
23 sum += *pop as floatY;
24 buckets += 1.0 as floatY;
25 }
26
27 16.0 as floatY * buckets + cost + sum * FastLog2(sum as u64) as floatY
30}
31
32pub struct EntropyBucketPopulation<AllocU32: alloc::Allocator<u32>> {
35 pub bucket_populations: AllocU32::AllocatedMemory,
36 pub cached_bit_entropy: floatY,
37}
38impl<AllocU32: alloc::Allocator<u32>> EntropyBucketPopulation<AllocU32> {
39 pub fn new(m32: &mut AllocU32) -> Self {
40 let size = 256 * 256;
41 EntropyBucketPopulation::<AllocU32> {
42 cached_bit_entropy: 0.0,
43 bucket_populations: m32.alloc_cell(size),
44 }
45 }
46 pub fn free(&mut self, m32: &mut AllocU32) {
47 m32.free_cell(core::mem::take(&mut self.bucket_populations));
48 }
49 fn clone_from(&mut self, other: &EntropyBucketPopulation<AllocU32>) {
50 self.bucket_populations
51 .slice_mut()
52 .clone_from_slice(other.bucket_populations.slice());
53 }
54 fn add_assign(&mut self, other: &EntropyBucketPopulation<AllocU32>) {
55 assert_eq!(
56 self.bucket_populations.slice().len(),
57 other.bucket_populations.slice().len()
58 );
59 for (item, other_item) in self
60 .bucket_populations
61 .slice_mut()
62 .iter_mut()
63 .zip(other.bucket_populations.slice().iter())
64 {
65 *item += *other_item;
66 }
67 self.cached_bit_entropy = HuffmanCost(self.bucket_populations.slice());
68 }
69 fn bzero(&mut self) {
71 self.cached_bit_entropy = 0.0;
72 for bp in self.bucket_populations.slice_mut().iter_mut() {
73 *bp = 0;
74 }
75 }
76 fn initiate_from(
78 &mut self,
79 rows: [&[Self]; 2],
80 rows_stride: [&[u8]; 2],
81 stride: u8,
82 do_clear: bool,
83 ) {
84 self.cached_bit_entropy = 0.0;
85 let mut found_any = false;
86 for (sub_row, sub_stride) in rows.iter().zip(rows_stride.iter()) {
87 for (item, istride) in sub_row.iter().zip(sub_stride.iter()) {
88 if *istride != stride {
89 continue; }
91 if do_clear && !found_any {
92 self.bucket_populations
93 .slice_mut()
94 .clone_from_slice(item.bucket_populations.slice());
95 found_any = true;
96 } else {
97 for (dst, src) in self
98 .bucket_populations
99 .slice_mut()
100 .iter_mut()
101 .zip(item.bucket_populations.slice().iter())
102 {
103 *dst += *src;
104 }
105 }
106 }
107 }
108 if do_clear && !found_any {
109 self.bzero();
110 } else {
111 self.cached_bit_entropy = HuffmanCost(self.bucket_populations.slice());
112 }
113 }
114 fn bit_cost_of_data_subset(
115 &mut self,
116 data0: &[u8],
117 mut stride: u8,
118 mut prev_bytes: [u8; NUM_STRIDES],
119 scratch: &mut EntropyBucketPopulation<AllocU32>,
120 ) -> floatY {
121 prev_bytes.reverse();
122 stride = cmp::max(1, stride); scratch
124 .bucket_populations
125 .slice_mut()
126 .clone_from_slice(self.bucket_populations.slice());
127 scratch.bucket_populations.slice_mut()[65535] += 1; scratch.bucket_populations.slice_mut()[65535] -= 1; let mut stray_count = 0.0 as floatY;
130 assert_eq!((NUM_STRIDES - 1) & NUM_STRIDES, 0); for (index, val) in data0.iter().enumerate() {
132 let prior_byte =
133 prev_bytes[(index + (NUM_STRIDES - stride as usize)) & (NUM_STRIDES - 1)];
134 let loc = &mut scratch.bucket_populations.slice_mut()
135 [prior_byte as usize * 256 + *val as usize];
136 if *loc == 0 {
137 stray_count += 1.0;
138 } else {
139 *loc -= 1;
140 }
141 prev_bytes[index & (NUM_STRIDES - 1)] = *val;
142 }
143 if self.cached_bit_entropy == 0.0 as floatY {
144 self.cached_bit_entropy = HuffmanCost(self.bucket_populations.slice());
145 }
146 debug_assert_eq!(
147 HuffmanCost(self.bucket_populations.slice()),
148 self.cached_bit_entropy
149 );
150
151 scratch.cached_bit_entropy = HuffmanCost(scratch.bucket_populations.slice());
152 self.cached_bit_entropy - scratch.cached_bit_entropy + stray_count * 8.0
153 }
154}
155
156const NUM_STRIDES: usize = 8;
157#[derive(Copy, Clone)]
158pub struct BucketPopIndex {
159 pub val: u8,
160 pub six_bits: u8,
161 pub stride: u8,
162}
163
164impl<AllocU32: alloc::Allocator<u32>> Index<BucketPopIndex> for EntropyBucketPopulation<AllocU32> {
165 type Output = u32;
166 fn index(&self, index: BucketPopIndex) -> &u32 {
167 &self.bucket_populations.slice()
168 [index.val as usize + index.six_bits as usize * 256 + index.stride as usize * 256 * 64]
169 }
170}
171impl<AllocU32: alloc::Allocator<u32>> IndexMut<BucketPopIndex>
172 for EntropyBucketPopulation<AllocU32>
173{
174 fn index_mut(&mut self, index: BucketPopIndex) -> &mut u32 {
175 &mut self.bucket_populations.slice_mut()
176 [index.val as usize + index.six_bits as usize * 256 + index.stride as usize * 256 * 64]
177 }
178}
179
180pub struct EntropyTally<AllocU32: alloc::Allocator<u32>> {
181 pop: [EntropyBucketPopulation<AllocU32>; NUM_STRIDES],
182}
183
184const NUM_LEVELS: usize = 4;
185const NUM_NODES: usize = (1 << (NUM_LEVELS)) - 1;
186pub const NUM_LEAF_NODES: usize = (NUM_NODES + 1) >> 1;
187
188pub struct EntropyPyramid<AllocU32: alloc::Allocator<u32>> {
189 pop: [EntropyBucketPopulation<AllocU32>; NUM_NODES],
190 stride: [u8; NUM_NODES],
191}
192
193impl<AllocU32: alloc::Allocator<u32>> EntropyPyramid<AllocU32> {
194 pub fn last_level_range(&self) -> Range<usize> {
195 (NUM_NODES - (1 << (NUM_LEVELS - 1)))..NUM_NODES
196 }
197 pub fn byte_index_to_pyramid_index(&self, byte_index: usize, metablock_size: usize) -> usize {
198 let range = self.last_level_range();
199 cmp::min(
200 range.start + (range.end - range.start) * byte_index / metablock_size,
201 range.end - 1,
202 ) }
204 pub fn reset_scratch_to_deepest_level(&self, output: &mut EntropyTally<AllocU32>) {
205 let mut has_modified = [false; NUM_STRIDES];
206 for index in self.last_level_range() {
208 if has_modified[self.stride[index] as usize] {
209 output.pop[self.stride[index] as usize].add_assign(&self.pop[index]);
210 } else {
211 output.pop[self.stride[index] as usize].clone_from(&self.pop[index]);
212 has_modified[self.stride[index] as usize] = true;
213 }
214 }
215 for stride in 0..NUM_STRIDES {
216 if !has_modified[stride] {
217 output.pop[stride].bzero();
218 output.pop[stride].cached_bit_entropy = 0.0;
219 } else {
220 output.pop[stride].cached_bit_entropy =
221 HuffmanCost(output.pop[stride].bucket_populations.slice());
222 }
223 }
225 }
226 pub fn stride_last_level_range(&self) -> [u8; NUM_LEAF_NODES] {
227 let mut ret = [0u8; NUM_LEAF_NODES];
228 ret.clone_from_slice(self.stride.split_at(self.stride.len() - NUM_LEAF_NODES).1);
229 ret
230 }
231 pub fn free(&mut self, m32: &mut AllocU32) {
232 for item in self.pop.iter_mut() {
233 item.free(m32);
234 }
235 }
236 pub fn disabled_placeholder(_m32: &mut AllocU32) -> Self {
237 EntropyPyramid::<AllocU32> {
238 pop: [
239 EntropyBucketPopulation::<AllocU32> {
240 cached_bit_entropy: 0.0,
241 bucket_populations: AllocU32::AllocatedMemory::default(),
242 },
243 EntropyBucketPopulation::<AllocU32> {
244 cached_bit_entropy: 0.0,
245 bucket_populations: AllocU32::AllocatedMemory::default(),
246 },
247 EntropyBucketPopulation::<AllocU32> {
248 cached_bit_entropy: 0.0,
249 bucket_populations: AllocU32::AllocatedMemory::default(),
250 },
251 EntropyBucketPopulation::<AllocU32> {
252 cached_bit_entropy: 0.0,
253 bucket_populations: AllocU32::AllocatedMemory::default(),
254 },
255 EntropyBucketPopulation::<AllocU32> {
256 cached_bit_entropy: 0.0,
257 bucket_populations: AllocU32::AllocatedMemory::default(),
258 },
259 EntropyBucketPopulation::<AllocU32> {
260 cached_bit_entropy: 0.0,
261 bucket_populations: AllocU32::AllocatedMemory::default(),
262 },
263 EntropyBucketPopulation::<AllocU32> {
264 cached_bit_entropy: 0.0,
265 bucket_populations: AllocU32::AllocatedMemory::default(),
266 },
267 EntropyBucketPopulation::<AllocU32> {
268 cached_bit_entropy: 0.0,
269 bucket_populations: AllocU32::AllocatedMemory::default(),
270 },
271 EntropyBucketPopulation::<AllocU32> {
272 cached_bit_entropy: 0.0,
273 bucket_populations: AllocU32::AllocatedMemory::default(),
274 },
275 EntropyBucketPopulation::<AllocU32> {
276 cached_bit_entropy: 0.0,
277 bucket_populations: AllocU32::AllocatedMemory::default(),
278 },
279 EntropyBucketPopulation::<AllocU32> {
280 cached_bit_entropy: 0.0,
281 bucket_populations: AllocU32::AllocatedMemory::default(),
282 },
283 EntropyBucketPopulation::<AllocU32> {
284 cached_bit_entropy: 0.0,
285 bucket_populations: AllocU32::AllocatedMemory::default(),
286 },
287 EntropyBucketPopulation::<AllocU32> {
288 cached_bit_entropy: 0.0,
289 bucket_populations: AllocU32::AllocatedMemory::default(),
290 },
291 EntropyBucketPopulation::<AllocU32> {
292 cached_bit_entropy: 0.0,
293 bucket_populations: AllocU32::AllocatedMemory::default(),
294 },
295 EntropyBucketPopulation::<AllocU32> {
296 cached_bit_entropy: 0.0,
297 bucket_populations: AllocU32::AllocatedMemory::default(),
298 },
299 ],
300 stride: [0; NUM_NODES],
301 }
302 }
303 pub fn new(m32: &mut AllocU32) -> Self {
304 let size = 256 * 256;
305 EntropyPyramid::<AllocU32> {
306 pop: [
307 EntropyBucketPopulation::<AllocU32> {
308 cached_bit_entropy: 0.0,
309 bucket_populations: m32.alloc_cell(size),
310 },
311 EntropyBucketPopulation::<AllocU32> {
312 cached_bit_entropy: 0.0,
313 bucket_populations: m32.alloc_cell(size),
314 },
315 EntropyBucketPopulation::<AllocU32> {
316 cached_bit_entropy: 0.0,
317 bucket_populations: m32.alloc_cell(size),
318 },
319 EntropyBucketPopulation::<AllocU32> {
320 cached_bit_entropy: 0.0,
321 bucket_populations: m32.alloc_cell(size),
322 },
323 EntropyBucketPopulation::<AllocU32> {
324 cached_bit_entropy: 0.0,
325 bucket_populations: m32.alloc_cell(size),
326 },
327 EntropyBucketPopulation::<AllocU32> {
328 cached_bit_entropy: 0.0,
329 bucket_populations: m32.alloc_cell(size),
330 },
331 EntropyBucketPopulation::<AllocU32> {
332 cached_bit_entropy: 0.0,
333 bucket_populations: m32.alloc_cell(size),
334 },
335 EntropyBucketPopulation::<AllocU32> {
336 cached_bit_entropy: 0.0,
337 bucket_populations: m32.alloc_cell(size),
338 },
339 EntropyBucketPopulation::<AllocU32> {
340 cached_bit_entropy: 0.0,
341 bucket_populations: m32.alloc_cell(size),
342 },
343 EntropyBucketPopulation::<AllocU32> {
344 cached_bit_entropy: 0.0,
345 bucket_populations: m32.alloc_cell(size),
346 },
347 EntropyBucketPopulation::<AllocU32> {
348 cached_bit_entropy: 0.0,
349 bucket_populations: m32.alloc_cell(size),
350 },
351 EntropyBucketPopulation::<AllocU32> {
352 cached_bit_entropy: 0.0,
353 bucket_populations: m32.alloc_cell(size),
354 },
355 EntropyBucketPopulation::<AllocU32> {
356 cached_bit_entropy: 0.0,
357 bucket_populations: m32.alloc_cell(size),
358 },
359 EntropyBucketPopulation::<AllocU32> {
360 cached_bit_entropy: 0.0,
361 bucket_populations: m32.alloc_cell(size),
362 },
363 EntropyBucketPopulation::<AllocU32> {
364 cached_bit_entropy: 0.0,
365 bucket_populations: m32.alloc_cell(size),
366 },
367 ],
368 stride: [0; NUM_NODES],
369 }
370 }
371 pub fn bit_cost_of_literals(
372 &mut self,
373 data0: &[u8],
374 start_index: u32,
375 metablock_len: usize,
376 stride: u8,
377 previous_bytes: [u8; NUM_STRIDES],
378 scratch: &mut EntropyTally<AllocU32>,
379 ) -> floatY {
380 assert!(stride as usize <= NUM_STRIDES);
381
382 self.pop[self.byte_index_to_pyramid_index(start_index as usize, metablock_len)]
383 .bit_cost_of_data_subset(data0, stride, previous_bytes, &mut scratch.pop[0])
384 }
385 fn populate_entry_stride1(&mut self, input: InputPair, index: u32) {
386 let mut prev_val = 0;
387 let pyr_item = &mut self.pop[index as usize];
388 pyr_item.bzero();
389 assert_eq!(pyr_item.bucket_populations.slice()[65535], 0);
390 for val in input.0.slice().iter().chain(input.1.slice().iter()) {
391 pyr_item.bucket_populations.slice_mut()[prev_val as usize * 256 + *val as usize] += 1;
392 prev_val = *val;
393 }
394 pyr_item.cached_bit_entropy = HuffmanCost(pyr_item.bucket_populations.slice());
395 self.stride[index as usize] = 0;
396 }
397 fn populate_entry(
398 &mut self,
399 input: InputPair,
400 scratch: &mut EntropyTally<AllocU32>,
401 index: u32,
402 mirror_range: Option<Range<usize>>,
403 prev_range: Option<Range<usize>>,
404 ) {
405 let mut initial_entropies = [0.0 as floatY; NUM_STRIDES];
406 let nothing: &[EntropyBucketPopulation<AllocU32>] = &[];
407 let nothing_u8: &[u8] = &[];
408 {
409 let pop_ranges = [
410 match mirror_range {
411 None => nothing,
412 Some(ref ir) => &self.pop[ir.clone()],
413 },
414 match prev_range {
415 None => nothing,
416 Some(ref pr) => &self.pop[pr.clone()],
417 },
418 ];
419 let stride_ranges = [
420 match mirror_range {
421 None => nothing_u8,
422 Some(ref ir) => &self.stride[ir.clone()],
423 },
424 match prev_range {
425 None => nothing_u8,
426 Some(ref pr) => &self.stride[pr.clone()],
427 },
428 ];
429 for stride in 0..NUM_STRIDES {
430 scratch.pop[stride].initiate_from(pop_ranges, stride_ranges, stride as u8, true);
431 initial_entropies[stride] = scratch.pop[stride].cached_bit_entropy;
432 }
433 }
434 scratch.observe_input_stream(input.0.slice(), input.1.slice());
435 let mut best_entropy_index = 0;
436 let mut min_entropy_value = (scratch.pop[0].cached_bit_entropy - initial_entropies[0]);
437 for stride in 1..NUM_STRIDES {
439 let entropy_value = scratch.pop[stride].cached_bit_entropy - initial_entropies[stride];
440 if entropy_value < min_entropy_value {
442 best_entropy_index = stride;
443 min_entropy_value = entropy_value;
444 }
445 }
446 self.pop[index as usize].clone_from(&scratch.pop[best_entropy_index]);
447 self.stride[index as usize] = best_entropy_index as u8;
448 }
449 pub fn populate_stride1(&mut self, input0: &[u8], input1: &[u8]) {
450 let input = InputPair(
451 InputReference {
452 data: input0,
453 orig_offset: 0,
454 },
455 InputReference {
456 data: input1,
457 orig_offset: input0.len(),
458 },
459 );
460 for i in 0..2 {
461 let first_range = if i == 0 {
462 input.split_at(input.len() >> 1).0
463 } else {
464 input.split_at(input.len() >> 1).1
465 };
466 for j in 0..2 {
467 let second_range = if j == 0 {
468 first_range.split_at(input.len() >> 2).0
469 } else {
470 first_range.split_at(input.len() >> 2).1
471 };
472 if NUM_LEVELS == 4 {
473 for k in 0..2 {
474 let third_range = if j == 0 {
475 second_range.split_at(input.len() >> 3).0
476 } else {
477 second_range.split_at(input.len() >> 3).1
478 };
479 self.populate_entry_stride1(third_range, 7 + ((i << 2) + (j << 1) + k));
480 }
481 } else {
482 assert_eq!(NUM_LEVELS, 3); self.populate_entry_stride1(second_range, 3 + ((i << 1) + j));
484 }
485 }
486 }
487 }
488 pub fn populate(&mut self, input0: &[u8], input1: &[u8], scratch: &mut EntropyTally<AllocU32>) {
489 let input = InputPair(
490 InputReference {
491 data: input0,
492 orig_offset: 0,
493 },
494 InputReference {
495 data: input1,
496 orig_offset: input0.len(),
497 },
498 );
499 self.populate_entry(input, scratch, 0, None, None); self.populate_entry(
503 input.split_at(input.len() >> 1).0,
504 scratch,
505 1,
506 Some(0..1),
507 None,
508 );
509 self.populate_entry(
510 input.split_at(input.len() >> 1).1,
511 scratch,
512 2,
513 None,
514 Some(1..2),
515 ); self.populate_entry(
519 input.split_at(input.len() >> 2).0,
520 scratch,
521 3,
522 Some(1..3),
523 None,
524 );
525 self.populate_entry(
526 input
527 .split_at(input.len() >> 1)
528 .0
529 .split_at(input.len() >> 2)
530 .1,
531 scratch,
532 4,
533 Some(2..3),
534 Some(3..4),
535 );
536 self.populate_entry(
537 input
538 .split_at(input.len() >> 1)
539 .1
540 .split_at(input.len() >> 2)
541 .0,
542 scratch,
543 5,
544 Some(3..5),
545 None,
546 );
547 self.populate_entry(
548 input
549 .split_at(input.len() >> 1)
550 .1
551 .split_at(input.len() >> 2)
552 .1,
553 scratch,
554 6,
555 Some(3..6),
556 None,
557 );
558 if NUM_LEVELS == 4 {
559 self.populate_entry(
561 input
562 .split_at(input.len() >> 1)
563 .0
564 .split_at(input.len() >> 2)
565 .0
566 .split_at(input.len() >> 3)
567 .0,
568 scratch,
569 7,
570 Some(4..7),
571 None,
572 );
573 self.populate_entry(
574 input
575 .split_at(input.len() >> 1)
576 .0
577 .split_at(input.len() >> 2)
578 .0
579 .split_at(input.len() >> 3)
580 .1,
581 scratch,
582 8,
583 Some(4..7),
584 Some(7..8),
585 );
586 self.populate_entry(
587 input
588 .split_at(input.len() >> 1)
589 .0
590 .split_at(input.len() >> 2)
591 .1
592 .split_at(input.len() >> 3)
593 .0,
594 scratch,
595 9,
596 Some(5..7),
597 Some(7..9),
598 );
599 self.populate_entry(
600 input
601 .split_at(input.len() >> 1)
602 .0
603 .split_at(input.len() >> 2)
604 .1
605 .split_at(input.len() >> 3)
606 .1,
607 scratch,
608 0xa,
609 Some(5..7),
610 Some(7..0xa),
611 );
612
613 self.populate_entry(
614 input
615 .split_at(input.len() >> 1)
616 .1
617 .split_at(input.len() >> 2)
618 .0
619 .split_at(input.len() >> 3)
620 .0,
621 scratch,
622 0xb,
623 Some(6..7),
624 Some(7..0xb),
625 );
626 self.populate_entry(
627 input
628 .split_at(input.len() >> 1)
629 .1
630 .split_at(input.len() >> 2)
631 .0
632 .split_at(input.len() >> 3)
633 .1,
634 scratch,
635 0xc,
636 Some(6..7),
637 Some(7..0xc),
638 );
639 self.populate_entry(
640 input
641 .split_at(input.len() >> 1)
642 .1
643 .split_at(input.len() >> 2)
644 .1
645 .split_at(input.len() >> 3)
646 .0,
647 scratch,
648 0xd,
649 None,
650 Some(7..0xd),
651 );
652 self.populate_entry(
653 input
654 .split_at(input.len() >> 1)
655 .1
656 .split_at(input.len() >> 2)
657 .1
658 .split_at(input.len() >> 3)
659 .1,
660 scratch,
661 0xe,
662 None,
663 Some(7..0xe),
664 );
665 } else {
666 assert_eq!(NUM_LEVELS, 3); }
668 }
669}
670
671impl<AllocU32: alloc::Allocator<u32>> EntropyTally<AllocU32> {
672 pub fn new(m32: &mut AllocU32, max_stride_arg: Option<u8>) -> EntropyTally<AllocU32> {
673 let size = 256 * 256;
674 let max_stride = max_stride_arg.unwrap_or(NUM_STRIDES as u8);
675 EntropyTally::<AllocU32> {
676 pop: [
677 EntropyBucketPopulation::<AllocU32> {
678 cached_bit_entropy: 0.0,
679 bucket_populations: if 0 < max_stride {
680 m32.alloc_cell(size)
681 } else {
682 AllocU32::AllocatedMemory::default()
683 },
684 },
685 EntropyBucketPopulation::<AllocU32> {
686 cached_bit_entropy: 0.0,
687 bucket_populations: if 1 < max_stride {
688 m32.alloc_cell(size)
689 } else {
690 AllocU32::AllocatedMemory::default()
691 },
692 },
693 EntropyBucketPopulation::<AllocU32> {
694 cached_bit_entropy: 0.0,
695 bucket_populations: if 2 < max_stride {
696 m32.alloc_cell(size)
697 } else {
698 AllocU32::AllocatedMemory::default()
699 },
700 },
701 EntropyBucketPopulation::<AllocU32> {
702 cached_bit_entropy: 0.0,
703 bucket_populations: if 3 < max_stride {
704 m32.alloc_cell(size)
705 } else {
706 AllocU32::AllocatedMemory::default()
707 },
708 },
709 EntropyBucketPopulation::<AllocU32> {
710 cached_bit_entropy: 0.0,
711 bucket_populations: if 4 < max_stride {
712 m32.alloc_cell(size)
713 } else {
714 AllocU32::AllocatedMemory::default()
715 },
716 },
717 EntropyBucketPopulation::<AllocU32> {
718 cached_bit_entropy: 0.0,
719 bucket_populations: if 5 < max_stride {
720 m32.alloc_cell(size)
721 } else {
722 AllocU32::AllocatedMemory::default()
723 },
724 },
725 EntropyBucketPopulation::<AllocU32> {
726 cached_bit_entropy: 0.0,
727 bucket_populations: if 6 < max_stride {
728 m32.alloc_cell(size)
729 } else {
730 AllocU32::AllocatedMemory::default()
731 },
732 },
733 EntropyBucketPopulation::<AllocU32> {
734 cached_bit_entropy: 0.0,
735 bucket_populations: if 7 < max_stride {
736 m32.alloc_cell(size)
737 } else {
738 AllocU32::AllocatedMemory::default()
739 },
740 },
741 ],
742 }
743 }
744 pub fn disabled_placeholder(m32: &mut AllocU32) -> EntropyTally<AllocU32> {
745 Self::new(m32, Some(0))
746 }
747 fn observe_input_stream(&mut self, input0: &[u8], input1: &[u8]) {
748 let mut priors = [0u8; NUM_STRIDES];
749 for val in input0.iter().chain(input1.iter()) {
750 for stride in 0..NUM_STRIDES {
751 self.pop[stride].bucket_populations.slice_mut()
752 [priors[stride] as usize * 256 + (*val as usize)] += 1;
753 }
754 {
755 let mut tmp = [0u8; NUM_STRIDES - 1];
756 tmp.clone_from_slice(&priors[..(NUM_STRIDES - 1)]);
757 priors[1..].clone_from_slice(&tmp[..]);
758 priors[0] = *val;
759 }
760 }
761 for stride in 0..NUM_STRIDES {
762 self.pop[stride].cached_bit_entropy =
763 HuffmanCost(self.pop[stride].bucket_populations.slice());
764 }
765 }
766 fn identify_best_population_and_update_cache(&mut self) -> u8 {
767 let mut old_bit_entropy: [floatY; NUM_STRIDES] = [0.0; NUM_STRIDES];
768 for (obe, be) in old_bit_entropy.iter_mut().zip(self.pop.iter_mut()) {
769 *obe = be.cached_bit_entropy;
770 if *obe != 0.0 {
771 be.cached_bit_entropy = HuffmanCost(be.bucket_populations.slice());
772 }
773 }
774 let mut best_stride = 0u8;
775 let mut best_entropy = self.pop[0].cached_bit_entropy - old_bit_entropy[0];
776 for index in 1..NUM_STRIDES {
778 let cur = self.pop[index].cached_bit_entropy - old_bit_entropy[index];
779 if (best_entropy == 0.0 || cur < best_entropy) && old_bit_entropy[index] > 0.0 {
781 best_stride = index as u8;
782 best_entropy = cur;
783 }
784 }
785 best_stride
786 }
787 pub fn peek(&mut self) -> &mut EntropyBucketPopulation<AllocU32> {
788 &mut self.pop[0]
789 }
790 pub fn get_previous_bytes(
791 &self,
792 input0: &[u8],
793 input1: &[u8],
794 bytes_processed: usize,
795 ) -> [u8; NUM_STRIDES] {
796 let mut retval = [0u8; NUM_STRIDES];
797 for index in 0..NUM_STRIDES {
798 let bp_offset = index + 1;
799 if bp_offset <= bytes_processed {
800 let offset = bytes_processed - bp_offset;
801 if offset >= input0.len() {
802 retval[index] = input1[offset - input0.len()];
803 } else {
804 retval[index] = input0[offset];
805 }
806 }
807 }
808 retval
809 }
810 pub fn pick_best_stride<InputReference: SliceWrapper<u8>>(
811 &mut self,
812 commands: &[interface::Command<InputReference>],
813 input0: &[u8],
814 input1: &[u8],
815 bytes_processed: &mut usize,
816 entropy_pyramid: &EntropyPyramid<AllocU32>,
817 stride_detection_quality: u8,
818 ) -> u8 {
819 if stride_detection_quality == 0 {
820 return 0;
821 }
822 if stride_detection_quality > 1 {
824 entropy_pyramid.reset_scratch_to_deepest_level(self);
825 }
826 let mut pyramid_byte_index: usize = 0;
827 for cmd in commands.iter() {
828 match *cmd {
829 interface::Command::Copy(ref copy) => {
830 *bytes_processed += copy.num_bytes as usize;
831 }
832 interface::Command::Dict(ref dict) => {
833 *bytes_processed += dict.final_size as usize;
834 }
835 interface::Command::Literal(ref lit) => {
836 if stride_detection_quality > 1 {
837 let mut priors = self.get_previous_bytes(input0, input1, *bytes_processed);
838 for (lindex, val) in lit.data.slice().iter().enumerate() {
839 if lindex == NUM_STRIDES {
840 let vpriors = self.get_previous_bytes(
841 input0,
842 input1,
843 NUM_STRIDES + *bytes_processed,
844 );
845 assert_eq!(vpriors, priors);
846 }
847 for (index, prior) in priors.iter().enumerate() {
848 self.pop[index].bucket_populations.slice_mut()
849 [256 * (*prior as usize) + *val as usize] += 1;
850 }
853 {
854 let mut tmp = [0u8; 7];
856 tmp.clone_from_slice(&priors[..7]);
857 priors[1..].clone_from_slice(&tmp[..]);
858 priors[0] = *val;
859 }
860 }
861 }
862 *bytes_processed += lit.data.slice().len();
863 pyramid_byte_index = *bytes_processed;
864 }
865 interface::Command::BlockSwitchCommand(_)
866 | interface::Command::BlockSwitchLiteral(_)
867 | interface::Command::BlockSwitchDistance(_)
868 | interface::Command::PredictionMode(_) => {}
869 }
870 }
871
872 if stride_detection_quality > 1 {
875 self.identify_best_population_and_update_cache() + 1
876 } else {
877 entropy_pyramid.stride[entropy_pyramid
878 .byte_index_to_pyramid_index(pyramid_byte_index, input0.len() + input1.len())]
879 + 1
880 }
881 }
882 pub fn free(&mut self, m32: &mut AllocU32) {
883 for item in self.pop.iter_mut() {
884 m32.free_cell(core::mem::take(&mut item.bucket_populations))
885 }
886 }
887 pub fn is_free(&mut self) -> bool {
888 self.pop[0].bucket_populations.slice().is_empty()
889 }
890}