1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//! Range coders (crate-internal).
//!
//! Two coders carry variant H in practice, and the context model is generic
//! over them through [`RangeDecoder`] and [`RangeEncoder`]:
//!
//! - Dmitry Subbotin's carry-less range coder, which RAR 2.9 through 4.x
//! uses for its PPMd blocks and Dmitry Shkarin's `.pmd` (7-Zip's `Ppmd7a`)
//! uses for its streams ([`CarrylessRangeDecoder`],
//! [`CarrylessRangeEncoder`]; `carryless.rs`), and
//! - Igor Pavlov's LZMA-style range coder with carry propagation, which the
//! 7z `PPMD` method uses ([`SevenZipRangeDecoder`],
//! [`SevenZipRangeEncoder`]; `sevenz.rs`).
//!
//! The coders hold registers only. A step codec keeps the registers between
//! calls and rebuilds a coder over the caller's slice for each call: the
//! decoders read through a [`SliceInput`] cursor (`cursor.rs`), the encoders
//! write through a [`Drain`] into the caller's slice (`output.rs`). Neither
//! side holds caller bytes.
//!
//! **Corrupt input.** Neither decoder ever panics or divides by zero. A
//! range scaled to zero (a frequency total past the range, which only a
//! corrupt stream or a corrupt model state produces) or a symbol size of
//! zero sets a sticky fault ([`RangeDecoder::faulted`]) and leaves the
//! arithmetic defined; the model turns the fault into a corrupt-stream
//! error. The carry-less decoder's RAR-style API
//! ([`CarrylessRangeDecoder::get_current_count`]) returns the error
//! directly.
pub use ;
pub use ;
pub use ;
pub use ;
/// RAR's name for the carry-less decoder: RAR 2.9 through 4.x PPMd blocks
/// are coded with it.
pub type RarRangeDecoder<I> = ;
/// `kTopValue` / `TOP`: both coders shift a byte in or out while the range
/// is below 2^24 (`Ppmd7Dec.c`, `Ppmd7aDec.c`).
pub const TOP: u32 = 1 << 24;
/// `kBot` / `BOT`: the carry-less coder's lower bound on the range
/// (`Ppmd7aDec.c`).
pub const BOT: u32 = 1 << 15;
/// Binary contexts code against a total of `PPMD_BIN_SCALE = 1 << 14`
/// (`Ppmd.h`), computed by shift rather than division.
pub const BIN_TOTAL_BITS: u32 = 14;
/// `PPMD_BIN_SCALE`.
pub const BIN_TOTAL: u32 = 1 << BIN_TOTAL_BITS;
/// The error a decoder's coder fault becomes: the stream is corrupt.
pub
/// The error an encoder's coder fault becomes: the model it encodes from
/// never produces one, so it is the codec's own failure, not the data's.
pub
/// The operations the context model decodes symbols through.
///
/// These are the three operations 7-Zip's `Ppmd7` model calls on its range
/// decoder (`GetThreshold`, `Decode`, `DecodeBit`). A coder implements each
/// with its own arithmetic; the model's output is bit-exact with the
/// reference only if the coder's arithmetic is too:
///
/// - **RAR** (Subbotin's carry-less coder): `get_threshold(t)` sets
/// `range /= t` and returns `(code - low) / range`; `decode(s, n)` sets
/// `low += s * range`, `range *= n`, then normalizes; `decode_bit(s0)`
/// sets `range >>= 14`, compares `(code - low) / range` with `s0`, and
/// decodes `(0, s0)` or `(s0, 2^14 - s0)` the same way. Normalization
/// shifts in a byte while `(low ^ (low + range)) < 2^24`, or while
/// `range < 2^15` after setting `range = -low & (2^15 - 1)`. All
/// arithmetic is wrapping `u32`.
/// - **7z** (Pavlov's coder): `get_threshold(t)` sets `range /= t` and
/// returns `code / range`; `decode(s, n)` sets `code -= s * range`,
/// `range *= n`, then normalizes; `decode_bit(s0)` computes
/// `bound = (range >> 14) * s0` and keeps `[0, bound)` or
/// `[bound, range)`.
///
/// Every call to [`decode`](Self::decode) and [`decode_bit`](Self::decode_bit)
/// normalizes before it returns, so the model never normalizes explicitly.
/// The operations the context model encodes symbols through: the mirror of
/// [`RangeDecoder`].
///
/// 7-Zip's encoder divides the range by the total in the model
/// (`R->Range /= SummFreq`) and then calls `RC_Encode(start, size)`; here the
/// division is part of [`encode`](Self::encode). Every call normalizes before
/// it returns, so the model never normalizes explicitly.