reed_solomon_novelpoly/field/
inc_encode.rs1#[inline(always)]
2pub fn encode_low(data: &[Additive], k: usize, codeword: &mut [Additive], n: usize) {
3 #[cfg(all(target_feature = "avx", feature = "avx"))]
4 if k >= 16 && k % 8 == 0 && n % 8 == 0 && (n - k) % 8 == 0 {
5 encode_low_faster8(data, k, codeword, n);
6 } else {
7 encode_low_plain(data, k, codeword, n);
8 }
9
10 #[cfg(not(all(target_feature = "avx", feature = "avx")))]
11 encode_low_plain(data, k, codeword, n);
12}
13
14pub fn encode_low_plain(data: &[Additive], k: usize, codeword: &mut [Additive], n: usize) {
16 assert!(k + k <= n);
17 assert_eq!(codeword.len(), n);
18 assert_eq!(data.len(), n);
19
20 assert!(is_power_of_2(n));
21 assert!(is_power_of_2(k));
22
23 assert_eq!((n / k) * k, n);
25
26 codeword.copy_from_slice(data);
28
29 let (codeword_first_k, codeword_skip_first_k) = codeword.split_at_mut(k);
31
32 inverse_afft(codeword_first_k, k, 0);
33
34 for shift in (k..n).step_by(k) {
39 let codeword_at_shift = &mut codeword_skip_first_k[(shift - k)..shift];
40
41 codeword_at_shift.copy_from_slice(codeword_first_k);
43 afft(codeword_at_shift, k, shift);
44 }
45
46 codeword[0..k].copy_from_slice(&data[0..k]);
48}
49
50#[cfg(all(target_feature = "avx", feature = "avx"))]
51pub fn encode_low_faster8(data: &[Additive], k: usize, codeword: &mut [Additive], n: usize) {
52 assert!(k + k <= n);
53 assert_eq!(codeword.len(), n);
54 assert_eq!(data.len(), n); assert!(is_power_of_2(n));
57 assert!(is_power_of_2(k));
58
59 assert_eq!(k % Additive8x::LANE, 0);
60 assert_eq!(n % Additive8x::LANE, 0);
61 assert_eq!((n - k) % Additive8x::LANE, 0);
62
63 assert_eq!((n / k) * k, n);
65
66 codeword.copy_from_slice(data);
68
69 let (codeword_first_k, codeword_skip_first_k) = codeword.split_at_mut(k);
71
72 assert!((k >> 1) >= Additive8x::LANE);
73 inverse_afft_faster8(codeword_first_k, k, 0);
74
75 for shift in (k..n).step_by(k) {
79 let codeword_at_shift = &mut codeword_skip_first_k[(shift - k)..shift];
80
81 codeword_at_shift.copy_from_slice(codeword_first_k);
83 afft_faster8(codeword_at_shift, k, shift);
84 }
85
86 codeword[0..k].copy_from_slice(&data[0..k]);
89}
90
91#[inline(always)]
94pub fn encode_high(data: &[Additive], k: usize, parity: &mut [Additive], mem: &mut [Additive], n: usize) {
95 #[cfg(all(target_feature = "avx", feature = "avx"))]
96 if (n - k) % Additive8x::LANE == 0 && n % Additive8x::LANE == 0 && k % Additive8x::LANE == 0 {
97 encode_high_faster8(data, k, parity, mem, n);
98 } else {
99 encode_high_plain(data, k, parity, mem, n);
100 }
101 #[cfg(not(target_feature = "avx"))]
102 encode_high_plain(data, k, parity, mem, n);
103}
104
105pub fn encode_high_plain(data: &[Additive], k: usize, parity: &mut [Additive], mem: &mut [Additive], n: usize) {
108 assert!(is_power_of_2(n));
109
110 let t: usize = n - k;
111
112 for i in 0..t {
114 parity[i] = Additive(0);
115 }
116
117 let mut i = t;
118 while i < n {
119 mem[..t].copy_from_slice(&data[(i - t)..t]);
120
121 inverse_afft(mem, t, i);
122 for j in 0..t {
123 parity[j] ^= mem[j];
124 }
125 i += t;
126 }
127 afft(parity, t, 0);
128}
129
130#[cfg(all(target_feature = "avx", feature = "avx"))]
131pub fn encode_high_faster8(data: &[Additive], k: usize, parity: &mut [Additive], mem: &mut [Additive], n: usize) {
132 let t: usize = n - k;
133 assert!(t >= 8);
134 assert_eq!(t % 8, 0);
135
136 for i in 0..t {
137 parity[i] = Additive::zero();
138 }
139
140 let mut i = t;
141 while i < n {
142 mem[..t].copy_from_slice(&data[(i - t)..t]);
143
144 inverse_afft_faster8(mem, t, i);
145 for j in 0..t {
146 parity[j] ^= mem[j];
147 }
148 i += t;
149 }
150 afft_faster8(parity, t, 0);
151}
152
153pub fn encode_sub(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive>> {
154 #[cfg(all(target_feature = "avx", feature = "avx"))]
155 if (k % Additive8x::LANE) == 0 && (k >> 1) >= Additive8x::LANE {
156 encode_sub_faster8(bytes, n, k)
157 } else {
158 encode_sub_plain(bytes, n, k)
159 }
160 #[cfg(not(all(target_feature = "avx", feature = "avx")))]
161 encode_sub_plain(bytes, n, k)
162}
163
164pub fn encode_sub_plain(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive>> {
166 assert!(is_power_of_2(n), "Algorithm only works for 2^i sizes for N");
167 assert!(is_power_of_2(k), "Algorithm only works for 2^i sizes for K");
168 assert!(bytes.len() <= k << 1);
169 assert!(k <= n / 2);
170
171 let bytes_len = bytes.len();
173 let upper_len = if is_power_of_2(bytes_len) {
174 bytes_len
175 } else {
176 let loglen = log2(bytes_len);
177 let upper_len = 1 << loglen;
178
179 if upper_len >= bytes_len {
180 upper_len
181 } else {
182 upper_len << 1
183 }
184 };
185 assert!(is_power_of_2(upper_len));
186 assert!(upper_len >= bytes_len);
187
188 let mut elm_data = vec![Additive(0); n];
191
192 for i in 0..((bytes_len + 1) / 2) {
193 elm_data[i] = Additive(Elt::from_be_bytes([
194 bytes.get(2 * i).copied().unwrap_or_default(),
195 bytes.get(2 * i + 1).copied().unwrap_or_default(),
196 ]));
197 }
198
199 let mut codeword = elm_data.clone();
203 assert_eq!(codeword.len(), n);
204
205 encode_low_plain(&elm_data[..], k, &mut codeword[..], n);
206
207 Ok(codeword)
208}
209
210#[cfg(all(target_feature = "avx", feature = "avx"))]
212pub fn encode_sub_faster8(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive>> {
213 assert!(is_power_of_2(n), "Algorithm only works for 2^i sizes for N");
214 assert!(is_power_of_2(k), "Algorithm only works for 2^i sizes for K");
215 assert!(bytes.len() <= k << 1);
216 assert!(k <= n / 2);
217 assert_eq!(k % Additive8x::LANE, 0);
218 assert!((k >> 1) >= Additive8x::LANE);
219
220 let bytes_len = bytes.len();
222 let upper_len = if is_power_of_2(bytes_len) {
223 bytes_len
224 } else {
225 let loglen = log2(std::cmp::max(Additive8x::LANE, bytes_len));
226 let upper_len = 1 << loglen;
227
228 if upper_len >= bytes_len {
229 upper_len
230 } else {
231 upper_len << 1
232 }
233 };
234 assert!(is_power_of_2(upper_len));
235 assert!(upper_len >= bytes_len);
236
237 let mut elm_data = vec![Additive(0); n];
240
241 for i in 0..((bytes_len + 1) / 2) {
242 elm_data[i] = Additive(Elt::from_be_bytes([
243 bytes.get(2 * i).copied().unwrap_or_default(),
244 bytes.get(2 * i + 1).copied().unwrap_or_default(),
245 ]));
246 }
247
248 let elm_len = elm_data.len();
251 assert_eq!(elm_len, n);
252
253 let mut codeword = elm_data.clone();
254 encode_low_faster8(&elm_data[..], k, &mut codeword[..], n);
255
256 Ok(codeword)
257}
258
259#[cfg(all(target_feature = "avx", feature = "avx"))]
260#[cfg(test)]
261mod tests_plain_vs_faster8 {
262 use super::*;
263
264 #[test]
265 fn encode_low_output_plain_eq_faster8() {
266 let n: usize = 32;
268 let k: usize = 16;
269 let data1 = vec![Additive(0x1234); n];
270 let data2 = data1.clone();
271
272 let mut parity1 = vec![Additive::zero(); n];
273 encode_low_plain(&data1[..], k, &mut parity1[..], n);
274
275 let mut parity2 = vec![Additive::zero(); n];
276 encode_low_faster8(&data2[..], k, &mut parity2[..], n);
277
278 assert_eq!(parity1, parity2);
279 }
280
281 #[cfg(all(target_feature = "avx", feature = "avx"))]
282 #[test]
283 fn encode_sub_output_plain_eq_faster8() {
284 let n = 64;
285 let k = 32; let bytes = vec![0x2A_u8; 64];
287 let bytes = bytes.as_slice();
288 let fe_plain = encode_sub_plain(bytes, n, k).unwrap();
289 let fe_faster8: Vec<Additive> = encode_sub_faster8(bytes, n, k).unwrap();
290
291 assert_eq!(fe_plain, fe_faster8);
292 }
293}