1use crate::block::{BlockCode, SoftDecode, container_traits, expect_len};
37use crate::conv::{BcjrWorkspace, Trellis, bcjr_into};
38use crate::interleaving::Interleaver;
39use comnum_core::signal::hard_decisions;
40use comnum_core::{Result, ensure};
41use comnum_math::Jacobian;
42
43pub const RANDOM_INTERLEAVER_SEED: u64 = 7;
46
47#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub struct TurboDecoder {
50 pub iterations: usize,
52 pub jacobian: Jacobian,
54}
55
56impl Default for TurboDecoder {
57 fn default() -> TurboDecoder {
59 TurboDecoder { iterations: 8, jacobian: Jacobian::Exact }
60 }
61}
62
63#[derive(Clone, Debug, PartialEq)]
65pub struct TurboCode {
66 trellis: Trellis,
68 interleaver: Interleaver,
70 pub decoder: TurboDecoder,
72}
73
74#[rustfmt::skip]
79const LTE_QPP: [(usize, usize, usize); 188] = [
80 (40, 3, 10), (48, 7, 12), (56, 19, 42), (64, 7, 16), (72, 7, 18), (80, 11, 20), (88, 5, 22),
81 (96, 11, 24), (104, 7, 26), (112, 41, 84), (120, 103, 90), (128, 15, 32), (136, 9, 34),
82 (144, 17, 108), (152, 9, 38), (160, 21, 120), (168, 101, 84), (176, 21, 44), (184, 57, 46),
83 (192, 23, 48), (200, 13, 50), (208, 27, 52), (216, 11, 36), (224, 27, 56), (232, 85, 58),
84 (240, 29, 60), (248, 33, 62), (256, 15, 32), (264, 17, 198), (272, 33, 68), (280, 103, 210),
85 (288, 19, 36), (296, 19, 74), (304, 37, 76), (312, 19, 78), (320, 21, 120), (328, 21, 82),
86 (336, 115, 84), (344, 193, 86), (352, 21, 44), (360, 133, 90), (368, 81, 46), (376, 45, 94),
87 (384, 23, 48), (392, 243, 98), (400, 151, 40), (408, 155, 102), (416, 25, 52), (424, 51, 106),
88 (432, 47, 72), (440, 91, 110), (448, 29, 168), (456, 29, 114), (464, 247, 58), (472, 29, 118),
89 (480, 89, 180), (488, 91, 122), (496, 157, 62), (504, 55, 84), (512, 31, 64), (528, 17, 66),
90 (544, 35, 68), (560, 227, 420), (576, 65, 96), (592, 19, 74), (608, 37, 76), (624, 41, 234),
91 (640, 39, 80), (656, 185, 82), (672, 43, 252), (688, 21, 86), (704, 155, 44), (720, 79, 120),
92 (736, 139, 92), (752, 23, 94), (768, 217, 48), (784, 25, 98), (800, 17, 80), (816, 127, 102),
93 (832, 25, 52), (848, 239, 106), (864, 17, 48), (880, 137, 110), (896, 215, 112), (912, 29, 114),
94 (928, 15, 58), (944, 147, 118), (960, 29, 60), (976, 59, 122), (992, 65, 124), (1008, 55, 84),
95 (1024, 31, 64), (1056, 17, 66), (1088, 171, 204), (1120, 67, 140), (1152, 35, 72),
96 (1184, 19, 74), (1216, 39, 76), (1248, 19, 78), (1280, 199, 240), (1312, 21, 82),
97 (1344, 211, 252), (1376, 21, 86), (1408, 43, 88), (1440, 149, 60), (1472, 45, 92),
98 (1504, 49, 846), (1536, 71, 48), (1568, 13, 28), (1600, 17, 80), (1632, 25, 102),
99 (1664, 183, 104), (1696, 55, 954), (1728, 127, 96), (1760, 27, 110), (1792, 29, 112),
100 (1824, 29, 114), (1856, 57, 116), (1888, 45, 354), (1920, 31, 120), (1952, 59, 610),
101 (1984, 185, 124), (2016, 113, 420), (2048, 31, 64), (2112, 17, 66), (2176, 171, 136),
102 (2240, 209, 420), (2304, 253, 216), (2368, 367, 444), (2432, 265, 456), (2496, 181, 468),
103 (2560, 39, 80), (2624, 27, 164), (2688, 127, 504), (2752, 143, 172), (2816, 43, 88),
104 (2880, 29, 300), (2944, 45, 92), (3008, 157, 188), (3072, 47, 96), (3136, 13, 28),
105 (3200, 111, 240), (3264, 443, 204), (3328, 51, 104), (3392, 51, 212), (3456, 451, 192),
106 (3520, 257, 220), (3584, 57, 336), (3648, 313, 228), (3712, 271, 232), (3776, 179, 236),
107 (3840, 331, 120), (3904, 363, 244), (3968, 375, 248), (4032, 127, 168), (4096, 31, 64),
108 (4160, 33, 130), (4224, 43, 264), (4288, 33, 134), (4352, 477, 408), (4416, 35, 138),
109 (4480, 233, 280), (4544, 357, 142), (4608, 337, 480), (4672, 37, 146), (4736, 71, 444),
110 (4800, 71, 120), (4864, 37, 152), (4928, 39, 462), (4992, 127, 234), (5056, 39, 158),
111 (5120, 39, 80), (5184, 31, 96), (5248, 113, 902), (5312, 41, 166), (5376, 251, 336),
112 (5440, 43, 170), (5504, 21, 86), (5568, 43, 174), (5632, 45, 176), (5696, 45, 178),
113 (5760, 161, 120), (5824, 89, 182), (5888, 323, 184), (5952, 47, 186), (6016, 23, 94),
114 (6080, 47, 190), (6144, 263, 480),
115];
116
117pub fn lte_qpp(k: usize) -> Option<(usize, usize)> {
120 LTE_QPP.binary_search_by_key(&k, |e| e.0).ok().map(|i| (LTE_QPP[i].1, LTE_QPP[i].2))
121}
122
123impl TurboCode {
124 pub fn lte(k: usize) -> Result<TurboCode> {
131 let interleaver = match lte_qpp(k) {
132 Some((f1, f2)) => Interleaver::qpp(k, f1, f2)?,
133 None => Interleaver::random(k, RANDOM_INTERLEAVER_SEED),
134 };
135 TurboCode::with_interleaver(interleaver)
136 }
137
138 pub fn with_interleaver(interleaver: Interleaver) -> Result<TurboCode> {
144 ensure(!interleaver.is_empty(), || "a turbo code needs at least one information bit".into())?;
145 let trellis = Trellis::recursive(4, 0o13, 0o15).unwrap_or_else(|_| unreachable!("a valid code"));
146 Ok(TurboCode { trellis, interleaver, decoder: TurboDecoder::default() })
147 }
148
149 pub fn trellis(&self) -> &Trellis {
151 &self.trellis
152 }
153
154 pub fn interleaver(&self) -> &Interleaver {
156 &self.interleaver
157 }
158
159 fn tail_len(&self) -> usize {
160 self.trellis.constraint as usize - 1
161 }
162
163 fn constituents(&self, llr: &[f64]) -> (Vec<f64>, Vec<f64>) {
167 let k = self.k();
168 let m = self.tail_len();
169 let (sys, rest) = llr.split_at(k);
170 let (p1, rest) = rest.split_at(k);
171 let (p2, tail) = rest.split_at(k);
172 let sys2 = self.interleaver.interleave(sys);
173 let mut a = Vec::with_capacity(2 * (k + m));
174 let mut b = Vec::with_capacity(2 * (k + m));
175 for i in 0..k {
176 a.extend([sys[i], p1[i]]);
177 b.extend([sys2[i], p2[i]]);
178 }
179 a.extend(&tail[..2 * m]);
180 b.extend(&tail[2 * m..]);
181 (a, b)
182 }
183}
184
185impl BlockCode for TurboCode {
186 fn k(&self) -> usize {
187 self.interleaver.len()
188 }
189
190 fn n(&self) -> usize {
191 3 * self.k() + 4 * self.tail_len()
192 }
193
194 fn encode_block(&self, info: &[u8]) -> Result<Vec<u8>> {
195 let k = self.k();
196 expect_len(info.len(), k, "bits")?;
197 let c1 = self.trellis.encode(info, true);
198 let c2 = self.trellis.encode(&self.interleaver.interleave(info), true);
199 let mut out = info.to_vec();
200 out.extend((0..k).map(|i| c1[2 * i + 1]));
201 out.extend((0..k).map(|i| c2[2 * i + 1]));
202 out.extend(&c1[2 * k..]);
203 out.extend(&c2[2 * k..]);
204 Ok(out)
205 }
206
207 fn decode_block(&self, llr: &[f64]) -> Result<Vec<u8>> {
208 Ok(hard_decisions(&self.app(llr, None)?))
209 }
210}
211
212impl SoftDecode for TurboCode {
213 fn app_into(&self, llr: &[f64], apriori: Option<&[f64]>, out: &mut [f64]) -> Result<usize> {
217 expect_len(llr.len(), self.n(), "LLRs")?;
218 let k = self.k();
219 expect_len(out.len(), k, "a posteriori LLRs")?;
220 let with_prior;
221 let llr = match apriori {
222 None => llr,
223 Some(a) => {
224 expect_len(a.len(), k, "a priori LLRs")?;
225 let mut v = llr.to_vec();
226 for (l, a) in v.iter_mut().zip(a) {
227 *l += a;
228 }
229 with_prior = v;
230 &with_prior
231 }
232 };
233 let sys = &llr[..k];
234 if self.decoder.iterations == 0 {
235 out.copy_from_slice(sys);
236 return Ok(0);
237 }
238 let m = self.tail_len();
239 let (a, b) = self.constituents(llr);
240 let sys2 = self.interleaver.interleave(sys);
241 iterate(&self.trellis, &self.trellis, &a, &b, sys, &sys2, self.interleaver.perm(), k + m, self.decoder, out)
242 }
243}
244
245container_traits!(TurboCode);
246
247#[allow(clippy::too_many_arguments, reason = "the two codes, their LLRs and the permutation")]
255pub(crate) fn iterate(
256 first: &Trellis,
257 second: &Trellis,
258 la: &[f64],
259 lb: &[f64],
260 sys: &[f64],
261 sys2: &[f64],
262 perm: &[usize],
263 steps: usize,
264 decoder: TurboDecoder,
265 out: &mut [f64],
266) -> Result<usize> {
267 let TurboDecoder { iterations, jacobian } = decoder;
268 let (mut la1, mut la2) = (vec![0.0; steps], vec![0.0; steps]);
271 let (mut app1, mut app2) = (Vec::with_capacity(steps), Vec::with_capacity(steps));
272 let mut ws = BcjrWorkspace::default();
273 for _ in 0..iterations {
274 bcjr_into(first, la, &la1, true, jacobian, &mut ws, &mut app1)?;
275 for (i, &p) in perm.iter().enumerate() {
276 la2[i] = app1[p] - la1[p] - sys[p];
277 }
278 bcjr_into(second, lb, &la2, true, jacobian, &mut ws, &mut app2)?;
279 for (i, &p) in perm.iter().enumerate() {
280 la1[p] = app2[i] - la2[i] - sys2[i];
281 }
282 }
283 for (i, &p) in perm.iter().enumerate() {
284 out[p] = app2[i];
285 }
286 Ok(iterations)
287}
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292
293 #[test]
294 fn the_lte_qpp_table_gives_permutations() {
295 assert_eq!((LTE_QPP[0], LTE_QPP[187]), ((40, 3, 10), (6144, 263, 480)));
296 assert!(LTE_QPP.windows(2).all(|w| w[0].0 < w[1].0));
297 for &(k, f1, f2) in <E_QPP {
298 assert!(Interleaver::qpp(k, f1, f2).is_ok(), "K = {k}");
299 }
300 assert_eq!(lte_qpp(432), Some((47, 72)));
301 assert_eq!(lte_qpp(41), None);
302 }
303 use crate::block::testing::awgn_llr;
304 use crate::bounds::bpsk_noise_variance;
305 use comnum_core::rng::Rng;
306
307 fn former_decode(code: &TurboCode, llr: &[f64]) -> Vec<u8> {
310 let k = code.k();
311 let m = code.tail_len();
312 let (a, b) = code.constituents(llr);
313 let sys = &llr[..k];
314 let sys2 = code.interleaver.interleave(sys);
315 let perm = code.interleaver.perm();
316 let (mut la1, mut la2) = (vec![0.0; k + m], vec![0.0; k + m]);
317 let (mut app1, mut app2) = (Vec::new(), Vec::new());
318 let mut ws = BcjrWorkspace::default();
319 for _ in 0..code.decoder.iterations.max(1) {
320 bcjr_into(&code.trellis, &a, &la1, true, code.decoder.jacobian, &mut ws, &mut app1).unwrap();
321 for (i, &p) in perm.iter().enumerate() {
322 la2[i] = app1[p] - la1[p] - sys[p];
323 }
324 bcjr_into(&code.trellis, &b, &la2, true, code.decoder.jacobian, &mut ws, &mut app2).unwrap();
325 for (i, &p) in perm.iter().enumerate() {
326 la1[p] = app2[i] - la2[i] - sys2[i];
327 }
328 }
329 let mut app = vec![0.0; k];
330 for (i, &p) in perm.iter().enumerate() {
331 app[p] = app2[i];
332 }
333 hard_decisions(&app)
334 }
335
336 #[test]
337 fn the_soft_output_gives_the_decisions_of_the_former_decoder() {
338 let mut r = Rng::new(4);
339 for jacobian in [Jacobian::Exact, Jacobian::MaxLog] {
340 let mut code = TurboCode::lte(104).unwrap();
341 code.decoder.jacobian = jacobian;
342 for _ in 0..10 {
343 let info: Vec<u8> = (0..104).map(|_| r.bit()).collect();
344 let s2 = bpsk_noise_variance(0.5, code.code_rate());
345 let y = awgn_llr(&code.encode_block(&info).unwrap(), s2, &mut r);
346 assert_eq!(code.decode_block(&y).unwrap(), former_decode(&code, &y));
347 }
348 }
349 let code = TurboCode::lte(40).unwrap();
351 let y: Vec<f64> = (0..code.n()).map(|_| r.gaussian()).collect();
352 let la: Vec<f64> = (0..40).map(|_| r.gaussian()).collect();
353 let mut shifted = y.clone();
354 shifted.iter_mut().zip(&la).for_each(|(v, a)| *v += a);
355 let (with, moved) = (code.app(&y, Some(&la)).unwrap(), code.app(&shifted, None).unwrap());
356 assert!(with.iter().zip(&moved).all(|(a, b)| a.to_bits() == b.to_bits()));
357 let none = TurboCode { decoder: TurboDecoder { iterations: 0, jacobian: Jacobian::Exact }, ..code.clone() };
359 assert_eq!(none.app(&y, None).unwrap(), y[..40]);
360 assert!(TurboCode::lte(0).is_err() && code.app(&y[1..], None).is_err());
361 }
362
363 #[test]
364 fn iterations_correct_more_errors() {
365 let mut code = TurboCode::with_interleaver(Interleaver::random(512, 9)).unwrap();
366 let mut r = Rng::new(2);
367 let (mut e1, mut e8) = (0usize, 0usize);
368 for _ in 0..20 {
369 let info: Vec<u8> = (0..512).map(|_| r.bit()).collect();
370 let c = code.encode_block(&info).unwrap();
371 let s2 = bpsk_noise_variance(1.0, code.code_rate());
373 let y = awgn_llr(&c, s2, &mut r);
374 code.decoder.iterations = 1;
375 e1 += code.decode_block(&y).unwrap().iter().zip(&info).filter(|(a, b)| a != b).count();
376 code.decoder.iterations = 8;
377 e8 += code.decode_block(&y).unwrap().iter().zip(&info).filter(|(a, b)| a != b).count();
378 }
379 assert!(e8 * 10 < e1.max(1), "1 iteration: {e1} errors, 8 iterations: {e8}");
380 }
381}