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
//! **The field the check bytes are computed in**: GF(2⁸), and the Reed-Solomon
//! remainder that is the whole of a QR symbol's error correction.
//!
//! # No tables, and that is the smaller answer
//!
//! Every implementation of this field reaches for a pair of 256-entry
//! logarithm and antilogarithm tables, because a table turns a multiply into
//! two lookups and an add. That trade is worth making when the multiply is on
//! a hot path. Here the whole encode is on the order of sixty thousand
//! multiplies for the largest symbol this seat can produce — microseconds —
//! and the tables would cost two arrays that have to be generated, held, and
//! indexed, in a crate where unchecked indexing is denied.
//!
//! So [`mul`] is the carry-less multiply itself, reduced by the standard's own
//! primitive polynomial. It is eight iterations of shift-and-conditional-xor,
//! it needs no initialization and no storage, and it is the definition rather
//! than a precomputation of one.
//!
//! # The polynomial, and why 0x1d and not 0x11d
//!
//! The field is generated by x⁸ + x⁴ + x³ + x² + 1 — `0x11d` as a nine-bit
//! number. The reduction below xors `0x1d`, which is the same polynomial with
//! its x⁸ term dropped: the term is exactly the bit that just shifted out of a
//! `u8`, so testing for it before the shift and xoring the remaining eight bits
//! after is the same arithmetic without ever needing a ninth bit to put it in.
/// The primitive polynomial's low eight bits — x⁸ + x⁴ + x³ + x² + 1, with the
/// x⁸ term left to the shift that produces it.
const REDUCTION: u8 = 0x1d;
/// **Multiply in GF(2⁸).** Carry-less multiplication, reduced at every step.
///
/// `p` accumulates the partial products (xor is addition in a field of
/// characteristic two), `a` doubles each round and is reduced whenever the
/// doubling would leave the byte, and `b` is consumed a bit at a time.
pub
/// **The generator polynomial for `count` check bytes**: the product of
/// (x − α⁰)(x − α¹)…(x − α^count-1), coefficients highest power first.
///
/// Subtraction is xor here, so the roots need no negation. Each round
/// multiplies the accumulated polynomial by one more linear factor, which is
/// the polynomial shifted up one degree xored with the polynomial scaled by
/// that factor's root — written as two iterators over the same coefficients,
/// offset by one, rather than as a walk over indices.
/// **The check bytes for one block**: `data` divided by the generator
/// polynomial for `count` roots, remainder only.
///
/// Synthetic division, one data byte per round. The remainder register holds
/// exactly `count` bytes; each round takes the byte leaving the top, xors the
/// next data byte into it to get the quotient term, shifts the register up, and
/// subtracts the generator scaled by that term. The generator's leading
/// coefficient is 1 and is what the shift accounts for, so the scaling walks
/// the coefficients *after* it — which is the `skip(1)`.
pub