// Reed-Solomon encoding/erasure decoding // Implementation of the algorithms described in // Efficient erasure decoding of Reed-Solomon codes // http://arxiv.org/abs/0901.1886v1 // (c) 2009 Frederic didier. // Any feedback is very welcome. For any question, comments, // see http://algo.epfl.ch/~didier/reed_solomon.html or email // frederic.didier@epfl.ch // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY // OF SUCH DAMAGE. // // ************************************************ // ************************************************ #include "reed_solomon.h" #include "stdlib.h" #include "stdio.h" int n_field; int n_walsh; int N_field; int N_walsh; int modulo; symbol *log_table; symbol *exp_table; symbol *product; symbol *lagrange; symbol *product_enc; symbol *log_walsh; symbol *pos; symbol *upos; // ************************************************ // ************************************************ // compute the tables for the finite field operations // exp_table is twice the needed size so we do not need to // perform a modulo each time. // list of some primitive polynomials int primitive[] = { 0,1,6, 0,3,7, 0,2,3,4,8, 0,4,9, 0,3,10, 0,2,11, 0,1,4,6,12, 0,1,3,4,13, 0,1,11,12,14, 0,1,15, 0,1,3,12,16, 0,3,17, 0,3,20, 0,3,25, 100 // fallback }; // will be set to the primitive poly of the field // used only by the fast algorithm version int *poly; int weight; void fill_table() { int i; for (i=0; i=n_field) break; pos++; } // used for the fast version only poly = &primitive[temp]; weight = pos-temp; if (primitive[pos]!=n_field) { printf("primitive poly for GF %d not found !\n", n_field); } // clock the lfsr (multiply by X) int state=1; for (i=0; i>n_field) state^=mask; if (state>>n_field!=0) exit(0); } // useful since later // log_table[1] = modulo exp_table[2*modulo]=1; } // ************************************************ // ************************************************ // Perform a Walsh transform and keep the coeffs mod (modulo) // The transformation is involutive if N_walsh = N_field. void walsh_mod(symbol *vect) { int i,j,step; step=1; while (step>n_field); b = (b & modulo) + (b>>n_field); vect[i]=a; vect[i+step]=b; i++; } i+=step; } step<<=1; } } void code_init(int nf, int nw) { int i; n_field = nf; n_walsh = nw; if (n_field>31 || n_walsh > n_field) { printf("incorrect field parameters\n"); exit(0); } N_field = 1< 16 // otherwise int is ok. for (i=0; imodulo) t-= modulo; product[j] = t; } } } // ******************************************************* // ******************************************************* // compute one redundancy piece // this is the heart of the encoding/decoding complexity // [data] contain the [K] known pieces and the log of the coefficients // [positions] contain their positions in the codeword // [x] is the index of the piece we want to compute // [output] is where we will write the result // both functions are almost identical // but it is useful to have two for profiling void quadratic_enc(int K, int S, symbol *data, symbol *output, int x) { int i,j; int m = product_enc[x]; // first time we overwrite output { // the second subtraction can also // go into quadratic_init int t = m - log_table[x] - product_enc[0]; if (t<0) t+= modulo; if (t<0) t+= modulo; // we set table[0] = 0 // because 0 correspond to a null coefficient // and not to a logarithm of 0. symbol *table = &exp_table[t]; t = table[0]; table[0]=0; symbol *o = output; for (j=0; j=K) lagrange[i] = exp_table[modulo - log_table[p ^ upos[i]] + log_table[p ^ x]]; } lagrange[x-K]=p^x; } else { // we want a 0 at old_pos (we have a 1 now) // we want a 1 at x // put the 0 for (i=0; i=K) lagrange[i] ^= exp_table[modulo - log_table[p ^ upos[i]] + log_table[p ^ old_pos]]; } // rescale to get the one int c = lagrange[x-K]; upos[x-K]=p; lagrange[x-K]=p ^ old_pos; for (i=0; i>j)&1; } // precompute the Walsh transforms of the inverse walsh_field(inverse); } void fast_clear() { free(codeword); free(coeff); free(inverse); } // ******************************************************* // ******************************************************* // compute field product of the vector coeff and inverse // for each [n_field] consecutive int of [inverse] and [coeff] // multiply them as if they were element of the field in the // standard basis. // // the difference is instead of coefficients in GF_2, // the coefficients are in Z ... // // The other limiting part in the complexity (with walsh_field). // The multiplication is quadratic in n_field // and is performed N_walsh time. void field_product() { int i,j,k; symbol s[64]; symbol *inv = inverse; for (k=0; k>j)&1; } } // compute the Walsh transforms of the coefficient walsh_field(coeff); // multiply with precomputed Walsh transform of the inverse field_product(); // walsh transform again walsh_field(coeff); // final multiplication by the product for (i=0; i> n_walsh) &1 ) << j; } if (t) { res[i] = exp_table[log_table[t] + product[i]]; } } } } // ******************************************************* // ******************************************************* void fast_encode(int N, int K, int S, symbol *data, symbol *packets) { int i,j; // fill pos for (i=0; i