reed_solomon/
decoder.rs

1use core;
2use ::gf::poly_math::*;
3use ::gf::poly::Polynom;
4use ::buffer::Buffer;
5use ::gf;
6
7/// Decoder error
8#[derive(Debug, Copy, Clone)]
9pub enum DecoderError {
10    /// Message is unrecoverably corrupted
11    TooManyErrors,
12}
13
14type Result<T> = core::result::Result<T, DecoderError>;
15
16/// Reed-Solomon BCH decoder
17#[derive(Debug, Copy, Clone)]
18pub struct Decoder {
19    ecc_len: usize,
20}
21
22impl Decoder {
23    /// Constructs a new `Decoder`.
24    ///
25    /// # Example
26    /// ```rust
27    /// use reed_solomon::Decoder;
28    ///
29    /// let decoder = Decoder::new(8);
30    /// ```
31    pub fn new(ecc_len: usize) -> Self {
32        Decoder { ecc_len: ecc_len }
33    }
34
35    /// Decodes block-encoded message and returns `Buffer` with corrected message and ecc offset.
36    /// Also includes the number of errors corrected.
37    ///
38    /// # Example
39    /// ```rust
40    /// use reed_solomon::Encoder;
41    /// use reed_solomon::Decoder;
42    ///
43    /// // Create encoder and decoder
44    /// let encoder = Encoder::new(4);
45    /// let decoder = Decoder::new(4);
46    ///
47    /// // Encode message
48    /// let mut encoded = encoder.encode(&[1, 2, 3, 4]);
49    ///
50    /// // Corrupt message
51    /// encoded[2] = 1;
52    /// encoded[3] = 2;
53    ///
54    /// // Let's assume it's known that `encoded[3]` is an error
55    /// let known_erasures = [3];
56    ///
57    /// // Decode and correct message,
58    /// let corrected = decoder.correct(&mut encoded, Some(&known_erasures)).unwrap();
59    ///
60    /// // Check results
61    /// assert_eq!(&[1, 2, 3, 4], corrected.data())
62    /// ```
63    pub fn correct_err_count(&self,
64                             msg: &[u8],
65                             erase_pos: Option<&[u8]>)
66                             -> Result<(Buffer, usize)> {
67       let mut msg = Buffer::from_slice(msg, msg.len() - self.ecc_len);
68
69        assert!(msg.len() < 256);
70
71        let erase_pos = if let Some(erase_pos) = erase_pos {
72            for e_pos in erase_pos {
73                msg[*e_pos as usize] = 0;
74            }
75            erase_pos
76        } else {
77            &[]
78        };
79
80        if erase_pos.len() > self.ecc_len {
81            return Err(DecoderError::TooManyErrors);
82        }
83
84        let synd = self.calc_syndromes(&msg);
85
86        // No errors
87        if synd.iter().all(|x| *x == 0) {
88            return Ok((msg,0));
89        }
90
91        let fsynd = self.forney_syndromes(&synd, erase_pos, msg.len());
92        let err_loc = try!(self.find_error_locator(&fsynd, None, erase_pos.len()));
93        let mut err_pos = try!(self.find_errors(&err_loc.reverse(), msg.len()));
94
95        // Append erase_pos to err_pos
96        for x in erase_pos.iter() {
97            err_pos.push(*x);
98        }
99
100        let (msg_out, fixed) = self.correct_errata(&msg, &synd, &err_pos);
101
102        // Check output message correctness
103        if self.is_corrupted(&msg_out) {
104            Err(DecoderError::TooManyErrors)
105        } else {
106            Ok((Buffer::from_polynom(msg_out, msg.len() - self.ecc_len), fixed))
107        }
108    }
109
110    /// Decodes block-encoded message and returns `Buffer` with corrected message and ecc offset.
111    ///
112    /// # Example
113    /// ```rust
114    /// use reed_solomon::Encoder;
115    /// use reed_solomon::Decoder;
116    ///
117    /// // Create encoder and decoder
118    /// let encoder = Encoder::new(4);
119    /// let decoder = Decoder::new(4);
120    ///
121    /// // Encode message
122    /// let mut encoded = encoder.encode(&[1, 2, 3, 4]);
123    ///
124    /// // Corrupt message
125    /// encoded[2] = 1;
126    /// encoded[3] = 2;
127    ///
128    /// // Let's assume it's known that `encoded[3]` is an error
129    /// let known_erasures = [3];
130    ///
131    /// // Decode and correct message,
132    /// let corrected = decoder.correct(&mut encoded, Some(&known_erasures)).unwrap();
133    ///
134    /// // Check results
135    /// assert_eq!(&[1, 2, 3, 4], corrected.data())
136    /// ```
137    pub fn correct(&self,
138                   msg: &[u8],
139                   erase_pos: Option<&[u8]>)
140                   -> Result<Buffer> {
141        self.correct_err_count(msg, erase_pos).map(|(r,_)| r)
142     }
143
144    /// Performs fast corruption check.
145    ///
146    /// # Example
147    /// ```rust
148    /// use reed_solomon::Encoder;
149    /// use reed_solomon::Decoder;
150    ///
151    /// // Create encoder and decoder
152    /// let encoder = Encoder::new(4);
153    /// let decoder = Decoder::new(4);
154    ///
155    /// // Encode message
156    /// let mut encoded = encoder.encode(&[1, 2, 3, 4]);
157    ///
158    /// assert_eq!(decoder.is_corrupted(&encoded), false);
159    ///
160    /// // Corrupt message
161    /// encoded[2] = 1;
162    /// encoded[3] = 2;
163    ///
164    /// assert_eq!(decoder.is_corrupted(&encoded), true);
165    /// ```
166    pub fn is_corrupted(&self, msg: &[u8]) -> bool {
167        (0..self.ecc_len).any(|x| msg.eval(gf::pow(2, x as i32)) != 0)
168    }
169
170    fn calc_syndromes(&self, msg: &[u8]) -> Polynom {
171        // index 0 is a pad for mathematical precision
172        let mut synd = Polynom::with_length(self.ecc_len + 1);
173        for i in 0..self.ecc_len {
174            uncheck_mut!(synd[i + 1]) = msg.eval(gf::pow(2, i as i32))
175        }
176
177        synd
178    }
179
180    fn find_errata_locator(&self, e_pos: &[u8]) -> Polynom {
181        let mut e_loc = polynom![1];
182
183        let add_lhs = [1];
184        let mut add_rhs = [0, 0];
185        for i in e_pos.iter() {
186            add_rhs[0] = gf::pow(2, *i as i32);
187            e_loc = e_loc.mul(&add_lhs.add(&add_rhs));
188        }
189
190        e_loc
191    }
192
193    fn find_error_evaluator(&self, synd: &[u8], err_loc: &[u8], syms: usize) -> Polynom {
194        let mut divisor = Polynom::with_length(syms + 2);
195        divisor[0] = 1;
196
197        let (_, remainder) = (synd.mul(err_loc)).div(&divisor);
198        remainder
199    }
200
201    /// Forney algorithm, computes the values (error magnitude) to correct the input message.
202    #[allow(non_snake_case)]
203    fn correct_errata(&self, msg: &[u8], synd: &[u8], err_pos: &[u8]) -> (Polynom, usize) {
204        // convert the positions to coefficients degrees
205        let mut coef_pos = Polynom::with_length(err_pos.len());
206        for (i, x) in err_pos.iter().enumerate() {
207            coef_pos[i] = msg.len() as u8 - 1 - x;
208        }
209
210        let err_loc = self.find_errata_locator(&coef_pos);
211        let synd = Polynom::from(synd);
212        let err_eval = self.find_error_evaluator(&synd.reverse(), &err_loc, err_loc.len() - 1)
213            .reverse();
214
215        let mut X = Polynom::new();
216
217        for px in coef_pos.iter() {
218            let l = (255 - px) as i32;
219            X.push(gf::pow(2, -l))
220        }
221
222        let mut E = Polynom::with_length(msg.len());
223        let mut fixed = 0;
224
225        let err_eval_rev = err_eval.reverse();
226        for (i, Xi) in X.iter().enumerate() {
227            let Xi_inv = gf::inverse(*Xi);
228
229            let mut err_loc_prime_tmp = Polynom::new();
230            for (j, Xj) in X.iter().enumerate() {
231                if j != i {
232                    err_loc_prime_tmp.push(gf::sub(1, gf::mul(Xi_inv, *Xj)));
233                }
234            }
235
236            let mut err_loc_prime = 1;
237            for coef in err_loc_prime_tmp.iter() {
238                err_loc_prime = gf::mul(err_loc_prime, *coef);
239            }
240
241            let y = err_eval_rev.eval(Xi_inv);
242            let y = gf::mul(gf::pow(*Xi, 1), y);
243
244            let magnitude = gf::div(y, err_loc_prime);
245
246            let E_index = uncheck!(err_pos[i]) as usize;
247            uncheck_mut!(E[E_index]) = magnitude;
248            fixed += 1;
249        }
250
251        (msg.add(&E), fixed)
252    }
253
254    #[allow(non_snake_case)]
255    fn find_error_locator(&self,
256                          synd: &[u8],
257                          erase_loc: Option<&[u8]>,
258                          erase_count: usize)
259                          -> Result<Polynom> {
260        let (mut err_loc, mut old_loc) = if let Some(erase_loc) = erase_loc {
261            (Polynom::from(erase_loc), Polynom::from(erase_loc))
262        } else {
263            (polynom![1], polynom![1])
264        };
265
266        let synd_shift = if synd.len() > self.ecc_len {
267            synd.len() - self.ecc_len
268        } else {
269            0
270        };
271
272        for i in 0..(self.ecc_len - erase_count) {
273            let K = if erase_loc.is_some() {
274                erase_count + i + synd_shift
275            } else {
276                i + synd_shift
277            };
278
279            let mut delta = uncheck!(synd[K]);
280            for j in 1..err_loc.len() {
281                let d_index = err_loc.len() - j - 1;
282                delta ^= gf::mul(err_loc[d_index], uncheck!(synd[K - j]));
283            }
284
285            old_loc.push(0);
286
287            if delta != 0 {
288                if old_loc.len() > err_loc.len() {
289                    let new_loc = old_loc.scale(delta);
290                    old_loc = err_loc.scale(gf::inverse(delta));
291                    err_loc = new_loc;
292                }
293
294                err_loc = err_loc.add(&old_loc.scale(delta));
295            }
296        }
297
298        let shift = err_loc.iter().take_while(|&&v| v == 0).count();
299        let err_loc = Polynom::from(&err_loc[shift..]);
300
301        let errs = err_loc.len() - 1;
302        let errs = if erase_count > errs {
303            erase_count
304        } else {
305            (errs - erase_count) * 2 + erase_count
306        };
307
308        if errs > self.ecc_len {
309            Err(DecoderError::TooManyErrors)
310        } else {
311            Ok(err_loc)
312        }
313    }
314
315    fn find_errors(&self, err_loc: &[u8], msg_len: usize) -> Result<Polynom> {
316        let errs = err_loc.len() - 1;
317        let mut err_pos = polynom![];
318
319        for i in 0..msg_len {
320            if err_loc.eval(gf::pow(2, i as i32)) == 0 {
321                let x = msg_len as u8 - 1 - i as u8;
322                err_pos.push(x);
323            }
324        }
325
326        if err_pos.len() != errs {
327            Err(DecoderError::TooManyErrors)
328        } else {
329            Ok(err_pos)
330        }
331    }
332
333    fn forney_syndromes(&self, synd: &[u8], pos: &[u8], msg_len: usize) -> Polynom {
334        let mut erase_pos_rev = Polynom::with_length(pos.len());
335        for (i, x) in pos.iter().enumerate() {
336            erase_pos_rev[i] = msg_len as u8 - 1 - x;
337        }
338
339        let mut fsynd = Polynom::from(&synd[1..]);
340
341        for pos in erase_pos_rev.iter() {
342            let x = gf::pow(2, *pos as i32);
343            for j in 0..(fsynd.len() - 1) {
344                fsynd[j] = gf::mul(fsynd[j], x) ^ fsynd[j + 1];
345            }
346        }
347
348        fsynd
349    }
350}
351
352#[cfg(test)]
353mod tests {
354    use super::*;
355    use ::Encoder;
356
357    #[test]
358    fn calc_syndromes() {
359        let px = [1, 2, 3, 4, 5, 6, 7, 8, 9];
360        let mut encoded = Encoder::new(8).encode(&px[..]);
361
362        assert_eq!([0; 9], *Decoder::new(8).calc_syndromes(&encoded));
363
364        encoded[5] = 1;
365
366        assert_eq!([0, 7, 162, 172, 245, 176, 71, 58, 180],
367                   *Decoder::new(8).calc_syndromes(&encoded));
368    }
369
370    #[test]
371    fn is_corrupted() {
372        let px = [1, 2, 3, 4, 5, 6, 7, 8, 9];
373        let mut encoded = Encoder::new(8).encode(&px[..]);
374
375        assert_eq!(false, Decoder::new(8).is_corrupted(&encoded));
376
377        encoded[5] = 1;
378
379        assert_eq!(true, Decoder::new(8).is_corrupted(&encoded));
380    }
381
382    #[test]
383    fn find_errata_locator() {
384        let e_pos = [19, 18, 17, 14, 15, 16];
385        assert_eq!([134, 207, 111, 227, 24, 150, 1],
386                   *Decoder::new(6).find_errata_locator(&e_pos[..]));
387    }
388
389    #[test]
390    fn find_error_evaluator() {
391        let synd = [232, 103, 78, 56, 109, 59, 242, 42, 64, 0];
392        let err_loc = [134, 207, 111, 227, 24, 150, 1];
393
394        assert_eq!([148, 151, 175, 126, 68, 64, 0],
395                   *Decoder::new(6).find_error_evaluator(&synd, &err_loc, 6));
396    }
397
398    #[test]
399    fn correct_errata() {
400        let msg = [0, 0, 0, 2, 2, 2, 119, 111, 114, 108, 100, 145, 124, 96, 105, 94, 31, 179, 149, 163];
401        let synd = [0, 64, 42, 242, 59, 109, 56, 78, 103, 232];
402        let err_pos = [0, 1, 2, 5, 4, 3];
403        let result = [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 145, 124, 96, 105, 94,
404                      31, 179, 149, 163];
405
406        assert_eq!(result,
407                   *Decoder::new(err_pos.len()).correct_errata(&msg, &synd, &err_pos).0);
408    }
409
410    #[test]
411    fn error_count() {
412        let msg = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
413        let encoder = Encoder::new(10);
414
415        let encoded = encoder.encode(&msg[..]);
416        let mut errd = *encoded;
417
418        errd[0] = 255;
419        errd[3] = 255;
420
421        let (_correct,err) = Decoder::new(10).correct_err_count(&errd, None).unwrap();
422
423        assert_eq!(err, 2);
424    }
425
426    #[test]
427    fn find_error_locator() {
428        let synd = [79, 25, 0, 160, 198, 122, 192, 169, 232];
429        let nsym = 9;
430        let erase_loc = None;
431        let erase_count = 3;
432
433        let result = [193, 144, 121, 1];
434
435        let error_loc = Decoder::new(nsym).find_error_locator(&synd, erase_loc, erase_count);
436
437        assert!(error_loc.is_ok());
438        assert_eq!(result, *error_loc.unwrap());
439    }
440
441    #[test]
442    fn find_errors() {
443        let err_loc = [1, 121, 144, 193];
444        let msg_len = 20;
445        let result = [5, 4, 3];
446
447        let err_pos = Decoder::new(6).find_errors(&err_loc, msg_len);
448
449        assert!(err_pos.is_ok());
450        assert_eq!(result, *err_pos.unwrap());
451
452        let err_loc = [1, 134, 181];
453        let msg_len = 12;
454
455        let err_pos = Decoder::new(6).find_errors(&err_loc, msg_len);
456
457        assert!(err_pos.is_err());
458    }
459
460    #[test]
461    fn forney_syndromes() {
462        let synd = [0, 64, 42, 242, 59, 109, 56, 78, 103, 232];
463        let pos = [0, 1, 2];
464        let nmess = 20;
465
466        let result = [79, 25, 0, 160, 198, 122, 192, 169, 232];
467        assert_eq!(result,
468                   *Decoder::new(6).forney_syndromes(&synd, &pos, nmess));
469    }
470
471    #[test]
472    fn decode() {
473        let mut msg = [0, 2, 2, 2, 2, 2, 119, 111, 114, 108, 100, 145, 124, 96, 105, 94, 31, 179, 149, 163];
474        let ecc = 9;
475        let erase_pos = [0, 1, 2];
476
477        let result = [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 145, 124, 96, 105, 94,
478                      31, 179, 149, 163];
479
480        let decoder = Decoder::new(ecc);
481        let decoded = decoder.correct(&mut msg[..], Some(&erase_pos)).unwrap();
482
483        assert_eq!(result, **decoded);
484    }
485}