1#![forbid(unsafe_code)]
2
3use crate::blocksort::block_sort;
4use crate::bzlib::{EState, BZ_MAX_SELECTORS, BZ_N_GROUPS, BZ_N_ITERS, BZ_RUNA, BZ_RUNB};
5use crate::{assert_h, debug_log, debug_logln, huffman};
6
7pub(crate) struct EWriter {
8 pub num_z: u32,
9 bs_live: i32,
10 bs_buff: u32,
11}
12
13pub(crate) struct LiveWriter<'a> {
14 zbits: &'a mut [u8],
15 writer: &'a mut EWriter,
16 num_z: u32,
17 bs_live: i32,
18 bs_buff: u32,
19}
20
21impl Drop for LiveWriter<'_> {
22 fn drop(&mut self) {
23 self.writer.num_z = self.num_z;
24 self.writer.bs_buff = self.bs_buff;
25 self.writer.bs_live = self.bs_live;
26 }
27}
28
29impl<'a> LiveWriter<'a> {
30 fn new(writer: &'a mut EWriter, zbits: &'a mut [u8]) -> Self {
31 Self {
32 num_z: writer.num_z,
33 bs_live: writer.bs_live,
34 bs_buff: writer.bs_buff,
35 zbits,
36 writer,
37 }
38 }
39
40 fn initialize(&mut self) {
41 self.bs_live = 0;
42 self.bs_buff = 0;
43 }
44
45 #[inline]
46 fn finish(&mut self) {
47 while self.bs_live > 0 {
48 self.zbits[self.num_z as usize] = (self.bs_buff >> 24) as u8;
49 self.num_z += 1;
50 self.bs_buff <<= 8;
51 self.bs_live -= 8;
52 }
53 }
54
55 #[inline]
56 fn flush_whole_bytes(&mut self) {
57 let range = self.num_z as usize..self.num_z as usize + 4;
58 if let Some(dst) = self.zbits.get_mut(range) {
59 dst.copy_from_slice(&self.bs_buff.to_be_bytes());
60 let bits_written = self.bs_live & !7;
61 self.bs_buff <<= bits_written;
62 self.bs_live -= bits_written;
63 self.num_z += (bits_written / 8) as u32;
64 }
65
66 while self.bs_live >= 8 {
67 self.zbits[self.num_z as usize] = (self.bs_buff >> 24) as u8;
68 self.num_z += 1;
69 self.bs_buff <<= 8;
70 self.bs_live -= 8;
71 }
72 }
73
74 fn write(&mut self, n: u8, v: u32) {
75 self.flush_whole_bytes();
76
77 self.bs_buff |= v << (32 - self.bs_live - i32::from(n));
78 self.bs_live += i32::from(n);
79 }
80
81 fn write_u8(&mut self, c: u8) {
82 self.write(8, c as u32);
83 }
84
85 fn write_u32(&mut self, u: u32) {
86 let [a, b, c, d] = u.to_le_bytes();
87
88 self.write(8, d as u32);
89 self.write(8, c as u32);
90 self.write(8, b as u32);
91 self.write(8, a as u32);
92 }
93}
94
95fn make_maps_e(s: &mut EState) {
96 s.nInUse = 0;
97 for (i, in_use) in s.inUse.iter().enumerate() {
98 if *in_use {
99 s.unseqToSeq[i] = s.nInUse as u8;
100 s.nInUse += 1;
101 }
102 }
103}
104
105fn generate_mtf_values(s: &mut EState) {
106 make_maps_e(s);
130 let EOB = s.nInUse + 1;
131
132 s.mtfFreq[..=EOB as usize].fill(0);
133
134 let mut wr = 0;
135 let mut zPend = 0;
136
137 let mut yy: [u8; 256] = [0; 256];
138 for i in 0..s.nInUse {
139 yy[i as usize] = i as u8;
140 }
141
142 for i in 0..s.nblock {
143 debug_assert!(wr <= i, "generateMTFValues(1)");
144 let mut j = s.arr1.ptr()[i as usize].wrapping_sub(1) as i32;
145 if j < 0 {
146 j += s.nblock;
147 }
148 let ll_i: u8 = s.unseqToSeq[s.arr2.block(s.nblock as usize)[j as usize] as usize];
149 debug_assert!((ll_i as i32) < s.nInUse, "generateMTFValues(2a)");
150
151 if yy[0] == ll_i {
152 zPend += 1;
153 } else {
154 if zPend > 0 {
155 zPend -= 1;
156 loop {
157 if zPend & 1 != 0 {
158 s.arr1.mtfv()[wr as usize] = 1;
159 wr += 1;
160 s.mtfFreq[1] += 1;
161 } else {
162 s.arr1.mtfv()[wr as usize] = 0;
163 wr += 1;
164 s.mtfFreq[0] += 1;
165 }
166 if zPend < 2 {
167 break;
168 }
169 zPend = (zPend - 2) / 2;
170 }
171 zPend = 0;
172 }
173
174 {
175 let mut rtmp: u8;
176 rtmp = yy[1];
177 yy[1] = yy[0];
178 j = 1;
179 while ll_i != rtmp {
180 j += 1;
181 core::mem::swap(&mut rtmp, &mut yy[j as usize]);
182 }
183 yy[0] = rtmp;
184 s.arr1.mtfv()[wr as usize] = (j + 1) as u16;
185 wr += 1;
186 s.mtfFreq[(j + 1) as usize] += 1;
187 }
188 }
189 }
190
191 if zPend > 0 {
192 zPend -= 1;
193 loop {
194 if zPend & 1 != 0 {
195 s.arr1.mtfv()[wr as usize] = BZ_RUNB;
196 wr += 1;
197 s.mtfFreq[BZ_RUNB as usize] += 1;
198 } else {
199 s.arr1.mtfv()[wr as usize] = BZ_RUNA;
200 wr += 1;
201 s.mtfFreq[BZ_RUNA as usize] += 1;
202 }
203 if zPend < 2 {
204 break;
205 }
206 zPend = (zPend - 2) / 2;
207 }
208 }
209
210 s.arr1.mtfv()[wr as usize] = EOB as u16;
211 wr += 1;
212 s.mtfFreq[EOB as usize] += 1;
213
214 s.nMTF = wr;
215}
216
217fn send_mtf_values(s: &mut EState) {
218 const BZ_LESSER_ICOST: u8 = 0;
219 const BZ_GREATER_ICOST: u8 = 15;
220
221 let mut gs: i32;
222 let mut ge: i32;
223 let mut totc: i32;
224 let mut bt: i32;
225 let mut bc: i32;
226 let mut nSelectors: usize = 0;
227 let mut selCtr: usize;
228 let mut nBytes: i32;
229
230 let mtfv = s.arr1.mtfv();
242
243 if s.verbosity >= 3 {
244 debug_logln!(
245 " {} in block, {} after MTF & 1-2 coding, {}+2 syms in use",
246 s.nblock,
247 s.nMTF,
248 s.nInUse,
249 );
250 }
251
252 let alphaSize = usize::try_from(s.nInUse + 2).unwrap_or(0);
253
254 for t in s.len.iter_mut() {
255 t[..alphaSize].fill(BZ_GREATER_ICOST);
256 }
257
258 assert_h!(s.nMTF > 0, 3001);
260 let nGroups: usize = match s.nMTF {
261 0..200 => 2,
262 200..600 => 3,
263 600..1200 => 4,
264 1200..2400 => 5,
265 _ => 6,
266 };
267
268 let mut cost: [u16; 6] = [0; 6];
269 let cost = &mut cost[..nGroups];
270
271 let mut fave: [i32; 6] = [0; 6];
272 let fave = &mut fave[..nGroups];
273
274 {
276 let mut tFreq: i32;
277 let mut aFreq: i32;
278
279 let mut nPart = nGroups;
280 let mut remF = s.nMTF;
281 let mut gs = 0i32;
282
283 while nPart > 0 {
284 tFreq = remF / nPart as i32;
285 ge = gs - 1;
286 aFreq = 0;
287 while aFreq < tFreq && ge < alphaSize as i32 - 1 {
288 ge += 1;
289 aFreq += s.mtfFreq[ge as usize];
290 }
291 if ge > gs && nPart != nGroups && nPart != 1 && (nGroups - nPart) % 2 == 1 {
292 aFreq -= s.mtfFreq[ge as usize];
293 ge -= 1;
294 }
295
296 if s.verbosity >= 3 {
297 debug_logln!(
298 " initial group {}, [{} .. {}], has {} syms ({:4.1}%)",
299 nPart,
300 gs,
301 ge,
302 aFreq,
303 100.0f64 * aFreq as f64 / s.nMTF as f64,
304 );
305 }
306
307 for v in 0..alphaSize {
308 s.len[nPart - 1][v] = if (gs..=ge).contains(&(v as i32)) {
309 BZ_LESSER_ICOST
310 } else {
311 BZ_GREATER_ICOST
312 };
313 }
314 nPart -= 1;
315 gs = ge + 1;
316 remF -= aFreq;
317 }
318 }
319
320 for iter in 0..BZ_N_ITERS {
324 fave.fill(0);
325
326 for t in 0..nGroups {
327 s.rfreq[t][..alphaSize].fill(0);
328 }
329
330 if nGroups == 6 {
335 for v in 0..alphaSize {
336 s.len_pack[v][0] = ((s.len[1][v] as u32) << 16) | (s.len[0][v] as u32);
337 s.len_pack[v][1] = ((s.len[3][v] as u32) << 16) | (s.len[2][v] as u32);
338 s.len_pack[v][2] = ((s.len[5][v] as u32) << 16) | (s.len[4][v] as u32);
339 }
340 }
341
342 nSelectors = 0;
343 totc = 0;
344 gs = 0;
345 loop {
346 if gs >= s.nMTF {
348 break;
349 }
350 ge = gs + 50 - 1;
351 if ge >= s.nMTF {
352 ge = s.nMTF - 1;
353 }
354
355 cost.fill(0);
360
361 if nGroups == 6 && 50 == ge - gs + 1 {
362 let mut cost01: u32 = 0;
363 let mut cost23: u32 = 0;
364 let mut cost45: u32 = 0;
365
366 for chunk in mtfv[gs as usize..][..50].chunks_exact(10) {
367 for icv in chunk {
368 let [a, b, c, _] = s.len_pack[usize::from(*icv)];
369 cost01 = cost01.wrapping_add(a);
370 cost23 = cost23.wrapping_add(b);
371 cost45 = cost45.wrapping_add(c);
372 }
373 }
374
375 cost[0] = (cost01 & 0xffff) as u16;
376 cost[1] = (cost01 >> 16) as u16;
377 cost[2] = (cost23 & 0xffff) as u16;
378 cost[3] = (cost23 >> 16) as u16;
379 cost[4] = (cost45 & 0xffff) as u16;
380 cost[5] = (cost45 >> 16) as u16;
381 } else {
382 for i in gs..=ge {
384 let icv_0: u16 = mtfv[i as usize];
385
386 for (t, c) in cost.iter_mut().enumerate() {
387 *c = (*c as i32 + s.len[t][icv_0 as usize] as i32) as u16;
388 }
389 }
390 }
391
392 bc = 999999999;
397 bt = -1;
398 for (t, &c) in cost.iter().enumerate() {
399 if (c as i32) < bc {
400 bc = c as i32;
401 bt = t as i32;
402 }
403 }
404 totc += bc;
405 fave[bt as usize] += 1;
406 s.selector[nSelectors] = bt as u8;
407 nSelectors += 1;
408
409 if nGroups == 6 && 50 == ge - gs + 1 {
410 for chunk in mtfv[gs as usize..][..50].chunks_exact(10) {
411 for &mtfv_i in chunk {
412 s.rfreq[bt as usize][usize::from(mtfv_i)] += 1;
413 }
414 }
415 } else {
416 for i in gs..=ge {
417 s.rfreq[bt as usize][mtfv[i as usize] as usize] += 1;
418 }
419 }
420
421 gs = ge + 1;
422 }
423
424 if s.verbosity >= 3 {
425 debug_log!(
426 " pass {}: size is {}, grp uses are ",
427 iter + 1,
428 totc / 8,
429 );
430 for f in fave.iter() {
431 debug_log!("{} ", f);
432 }
433 debug_logln!();
434 }
435
436 for t in 0..nGroups {
442 huffman::make_code_lengths(&mut s.len[t], &s.rfreq[t], alphaSize, 17);
443 }
444 }
445
446 assert_h!(nGroups < 8, 3002);
447 assert_h!(nSelectors < 32768, 3003);
448 assert_h!(nSelectors <= usize::from(BZ_MAX_SELECTORS), 3003);
449
450 {
452 let mut pos: [u8; BZ_N_GROUPS] = [0, 1, 2, 3, 4, 5];
453
454 let mut tmp2: u8;
455 let mut tmp: u8;
456
457 for (i, &ll_i) in s.selector[..nSelectors].iter().enumerate() {
458 let mut j = 0;
459 tmp = pos[j as usize];
460 while ll_i != tmp {
461 j += 1;
462 tmp2 = tmp;
463 tmp = pos[j as usize];
464 pos[j as usize] = tmp2;
465 }
466 pos[0] = tmp;
467 s.selectorMtf[i] = j as u8;
468 }
469 }
470
471 for (t, len) in s.len[..nGroups].iter().enumerate() {
473 let len = &len[..alphaSize];
474
475 let mut minLen = 32;
476 let mut maxLen = 0;
477
478 for &l in len {
479 maxLen = Ord::max(maxLen, l);
480 minLen = Ord::min(minLen, l);
481 }
482
483 assert_h!(maxLen <= 17, 3004);
484 assert_h!(minLen >= 1, 3005);
485
486 huffman::assign_codes(&mut s.code[t], len, minLen, maxLen);
487 }
488
489 let mut writer = LiveWriter::new(&mut s.writer, s.arr2.zbits(s.nblock as usize));
491
492 {
493 let inUse16: [bool; 16] =
494 core::array::from_fn(|i| s.inUse[i * 16..][..16].iter().any(|x| *x));
495
496 nBytes = writer.num_z as i32;
497 for in_use in inUse16 {
498 writer.write(1, in_use as u32);
499 }
500 for (i, any_in_use) in inUse16.iter().enumerate() {
501 if *any_in_use {
502 for j in 0..16 {
503 writer.write(1, s.inUse[i * 16 + j] as u32);
504 }
505 }
506 }
507 if s.verbosity >= 3 {
508 debug_log!(" bytes: mapping {}, ", writer.num_z as i32 - nBytes,);
509 }
510 }
511
512 nBytes = writer.num_z as i32;
514 writer.write(3, nGroups as u32);
515 writer.write(15, nSelectors as u32);
516
517 for i in 0..nSelectors {
518 for _ in 0..s.selectorMtf[i] {
519 writer.write(1, 1);
520 }
521 writer.write(1, 0);
522 }
523 if s.verbosity >= 3 {
524 debug_log!("selectors {}, ", writer.num_z as i32 - nBytes);
525 }
526
527 nBytes = writer.num_z as i32;
529
530 for t in 0..nGroups {
531 let mut curr = s.len[t][0];
532 writer.write(5, curr as u32);
533 for i in 0..alphaSize {
534 while curr < s.len[t][i] {
535 writer.write(2, 2);
536 curr += 1;
537 }
538 while curr > s.len[t][i] {
539 writer.write(2, 3);
540 curr -= 1;
541 }
542 writer.write(1, 0);
543 }
544 }
545 if s.verbosity >= 3 {
546 debug_log!("code lengths {}, ", writer.num_z as i32 - nBytes);
547 }
548
549 nBytes = writer.num_z as i32;
551 selCtr = 0;
552 gs = 0;
553 loop {
554 if gs >= s.nMTF {
555 break;
556 }
557 ge = gs + 50 - 1;
558 if ge >= s.nMTF {
559 ge = s.nMTF - 1;
560 }
561 assert_h!((s.selector[selCtr] as usize) < nGroups, 3006);
562 if nGroups == 6 && 50 == ge - gs + 1 {
563 let s_len_sel_selCtr = s.len[s.selector[selCtr] as usize];
566 let s_code_sel_selCtr = s.code[s.selector[selCtr] as usize];
567
568 for chunk in mtfv[gs as usize..][..50].chunks_exact(10) {
569 for &mtfv_i in chunk {
570 writer.write(
571 s_len_sel_selCtr[usize::from(mtfv_i)],
572 s_code_sel_selCtr[usize::from(mtfv_i)],
573 );
574 }
575 }
576 } else {
577 for i in gs..=ge {
579 writer.write(
580 s.len[s.selector[selCtr] as usize][mtfv[i as usize] as usize],
581 s.code[s.selector[selCtr] as usize][mtfv[i as usize] as usize],
582 );
583 }
584 }
585 gs = ge + 1;
586 selCtr += 1;
587 }
588 assert_h!(selCtr == nSelectors, 3007);
589
590 if s.verbosity >= 3 {
591 debug_logln!("codes {}", writer.num_z as i32 - nBytes);
592 }
593}
594
595pub(crate) fn compress_block(s: &mut EState, is_last_block: bool) {
596 if s.nblock > 0 {
597 s.blockCRC = !s.blockCRC;
598 s.combinedCRC = s.combinedCRC.rotate_left(1);
599 s.combinedCRC ^= s.blockCRC;
600 if s.blockNo > 1 {
601 s.writer.num_z = 0;
602 }
603
604 if s.verbosity >= 2 {
605 debug_logln!(
606 " block {}: crc = 0x{:08x}, combined CRC = 0x{:08x}, size = {}",
607 s.blockNo,
608 s.blockCRC,
609 s.combinedCRC,
610 s.nblock,
611 );
612 }
613
614 block_sort(s);
615 }
616
617 {
618 if s.blockNo == 1 {
620 let mut writer = LiveWriter::new(&mut s.writer, s.arr2.zbits(s.nblock as usize));
621
622 writer.initialize();
623 writer.write_u8(b'B');
624 writer.write_u8(b'Z');
625 writer.write_u8(b'h');
626 writer.write_u8(b'0' + s.blockSize100k as u8);
627 }
628
629 if s.nblock > 0 {
630 let mut writer = LiveWriter::new(&mut s.writer, s.arr2.zbits(s.nblock as usize));
631
632 writer.write_u8(0x31);
633 writer.write_u8(0x41);
634 writer.write_u8(0x59);
635 writer.write_u8(0x26);
636 writer.write_u8(0x53);
637 writer.write_u8(0x59);
638
639 writer.write_u32(s.blockCRC);
641
642 writer.write(1, 0);
652
653 writer.write(24, s.origPtr as u32);
654
655 drop(writer);
656
657 generate_mtf_values(s);
658
659 send_mtf_values(s);
660 }
661 }
662
663 if is_last_block {
665 let mut writer = LiveWriter::new(&mut s.writer, s.arr2.zbits(s.nblock as usize));
666
667 writer.write_u8(0x17);
668 writer.write_u8(0x72);
669 writer.write_u8(0x45);
670 writer.write_u8(0x38);
671 writer.write_u8(0x50);
672 writer.write_u8(0x90);
673 writer.write_u32(s.combinedCRC);
674
675 if s.verbosity >= 2 {
676 debug_log!(" final combined CRC = 0x{:08x}\n ", s.combinedCRC);
677 }
678
679 writer.finish();
680 }
681}