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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/// Encoding, decoding, compression, and decompression algorithms.
///
/// Implements FIPS 203 Section 4.2.1, Algorithms 3-6:
///
/// - [`byte_encode`] / [`byte_decode`] -- bit-pack/unpack 256 integers into/from bytes
/// - [`compress`] / [`decompress`] -- lossy compression between Z_q and Z_{2^d}
/// - [`compress_poly`] / [`decompress_poly`] -- vectorized compression over full polynomials
use ;
/// Bit-pack 256 integers into `32*d` bytes (Algorithm 5: ByteEncode_d).
///
/// Each of the 256 coefficients in `f` is encoded using `d` bits.
/// For `d < 12`, coefficients are treated modulo `2^d`.
/// For `d = 12`, coefficients are treated modulo q = 3329.
///
/// # Arguments
///
/// * `d` - The bit-width per coefficient (1..=12).
/// * `f` - Array of 256 unsigned 16-bit coefficients.
/// * `out` - Output buffer of exactly `32 * d` bytes.
///
/// # Panics
///
/// Debug-asserts that `out.len() == 32 * d`.
/// Unpack `32*d` bytes into 256 integers (Algorithm 6: ByteDecode_d).
///
/// The inverse of [`byte_encode`]. Each coefficient is extracted from `d`
/// consecutive bits and reduced modulo `2^d` (for `d < 12`) or modulo
/// q = 3329 (for `d = 12`).
///
/// # Arguments
///
/// * `d` - The bit-width per coefficient (1..=12).
/// * `input` - Input buffer of exactly `32 * d` bytes.
/// * `f` - Output array of 256 unsigned 16-bit coefficients.
///
/// # Panics
///
/// Debug-asserts that `input.len() == 32 * d`.
/// Lossy compression from Z_q to Z_{2^d} (FIPS 203 eq. 4.7).
///
/// Computes `x -> round(2^d / q * x) mod 2^d` using integer-only
/// arithmetic: `floor((2^d * x + q/2) / q) mod 2^d`.
///
/// # Arguments
///
/// * `d` - Target bit-width (1..=12).
/// * `x` - A coefficient in `[0, q-1]`.
///
/// # Returns
///
/// The compressed value in `[0, 2^d - 1]`.
/// Decompression from Z_{2^d} back to Z_q (FIPS 203 eq. 4.8).
///
/// Computes `y -> round(q / 2^d * y)` using integer-only arithmetic:
/// `floor((q * y + 2^{d-1}) / 2^d)`.
///
/// This is the approximate inverse of [`compress`]. The round-trip
/// introduces a bounded quantization error.
///
/// # Arguments
///
/// * `d` - Source bit-width (1..=12).
/// * `y` - A compressed value in `[0, 2^d - 1]`.
///
/// # Returns
///
/// The decompressed value in `[0, q-1]`.
/// Compress all 256 coefficients of a polynomial from Z_q to Z_{2^d}.
///
/// Applies [`compress`] element-wise.
///
/// # Arguments
///
/// * `d` - Target bit-width.
/// * `f` - Input polynomial with coefficients in `[0, q-1]`.
/// * `out` - Output polynomial with coefficients in `[0, 2^d - 1]`.
/// Decompress all 256 coefficients of a polynomial from Z_{2^d} to Z_q.
///
/// Applies [`decompress`] element-wise.
///
/// # Arguments
///
/// * `d` - Source bit-width.
/// * `f` - Input polynomial with coefficients in `[0, 2^d - 1]`.
/// * `out` - Output polynomial with coefficients in `[0, q-1]`.