// 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" // ************************************************ // ************************************************ int n_field; int N_field; int modulo; symbol *log_table; symbol *exp_table; uint8_t *mult_table; // ************************************************ // ************************************************ // 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; // contain the primitive poly in binary form // used in xor type field multiplication int field_mask; // init field. void fill_table(int nf) { n_field = nf; N_field = 1<=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; int i; for (i=0; i>n_field) state^=field_mask; if (state>>n_field!=0) exit(0); } // useful since later // since log_table[0]=0 // we set log_table[1]=modulo // so log_table is a bijection... log_table[0]=0; log_table[1]=modulo; exp_table[2*modulo]=1; // for GF(2^8) if (n_field==8) { int i,j; mult_table = (uint8_t *) malloc(256*256); for (i=0; i<256; i++) for (j=0; j<256; j++) { if (j==0) mult_table[i*256+j]=0; else mult_table[i*256+j]=exp_table[i+log_table[j]]; } } } // ******************************************************* // ******************************************************* void packet_clear(void *p, int S) { memset(p, 0, S); } void packet_log(void *p, int S) { int i; uint8_t *pt = (uint8_t *)p; for (i=0; i> j)&1) { uint32_t *src = (uint32_t *) (p_src + i*seg_size); uint32_t *dst = (uint32_t *) (p_dst + j*seg_size); for (k=0; k>n_field) cte^=field_mask; } } // less efficient even with inline ?? void process_packet_xor2(int log_cte, void *p_dst, void *p_src, int S) { int i,j; int seg_size = S / n_field; int cte = exp_table[log_cte]; for (i=0; i> j)&1) { memxor(p_dst+j*seg_size, p_src+i*seg_size, seg_size); } } // multiply cte by X cte <<=1; if (cte>>n_field) cte^=field_mask; } } void process_packet_xor_eq(int log_cte, void *p_dst, void *p_src, int S) { memset(p_dst, 0, S); process_packet_xor(log_cte, p_dst, p_src, S); } // ******************************************************* // ******************************************************* int multiply(int a, int b) { int i; int res=0; for (i=0; i> n_field) a^=field_mask; b >>=1; } return res; } void process_packet_direct_simple(int log_cte, void *p_dst, void *p_src, int S) { int i; int cte = exp_table[log_cte]; uint16_t *src = (uint16_t *)p_src; uint16_t *dst = (uint16_t *)p_dst; for (i=0; i> n_field) cte^=field_mask; } uint16_t *src = (uint16_t *)p_src; uint16_t *dst = (uint16_t *)p_dst; for (i=0; i>0)&1)) & table[0]; res ^= (-((a>>1)&1)) & table[1]; res ^= (-((a>>2)&1)) & table[2]; res ^= (-((a>>3)&1)) & table[3]; res ^= (-((a>>4)&1)) & table[4]; res ^= (-((a>>5)&1)) & table[5]; res ^= (-((a>>6)&1)) & table[6]; res ^= (-((a>>7)&1)) & table[7]; res ^= (-((a>>8)&1)) & table[8]; res ^= (-((a>>9)&1)) & table[9]; res ^= (-((a>>10)&1)) & table[10]; res ^= (-((a>>11)&1)) & table[11]; res ^= (-((a>>12)&1)) & table[12]; res ^= (-((a>>13)&1)) & table[13]; res ^= (-((a>>14)&1)) & table[14]; res ^= (-((a>>15)&1)) & table[15]; *dst++ ^= res; } } void process_packet_direct_eq16(int log_cte, void *p_dst, void *p_src, int S) { memset(p_dst, 0, S); process_packet_direct16(log_cte, p_dst, p_src, S); } void process_packet_direct8(int log_cte, void *p_dst, void *p_src, int S) { int i; int cte = exp_table[log_cte]; int table[8]; for (i=0;i> n_field) cte^=field_mask; } uint8_t *src = (uint8_t *)p_src; uint8_t *dst = (uint8_t *)p_dst; for (i=0; i>0)&1)) & table[0]; res ^= (-((a>>1)&1)) & table[1]; res ^= (-((a>>2)&1)) & table[2]; res ^= (-((a>>3)&1)) & table[3]; res ^= (-((a>>4)&1)) & table[4]; res ^= (-((a>>5)&1)) & table[5]; res ^= (-((a>>6)&1)) & table[6]; res ^= (-(a>>7)) & table[7]; *dst++ ^= res; } } void process_packet_direct_eq8(int log_cte, void *p_dst, void *p_src, int S) { memset(p_dst, 0, S); process_packet_direct8(log_cte, p_dst, p_src, S); } // ******************************************************* // ******************************************************* // these functions need the src packet // to be in log form void process_packet_table(int log_cte, void *p_dst, void *p_src, int S) { symbol *table = &exp_table[log_cte]; int t = table[0]; table[0]=0; int i; uint8_t *src = (uint8_t *)p_src; uint8_t *dst = (uint8_t *)p_dst; for (i=0; i>n_field); b = (b & modulo) + (b>>n_field); vect[i]=a; vect[i+step]=b; i++; } i+=step; } step<<=1; } } void code_init(int nw) { 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; } } } // ******************************************************* // ******************************************************* // for encoding, we can precompute the product once void encode_init(int N, int K) { int i; // fill pos for (i=0; i