/*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org) You can redistribute this library and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.*/ #include "bch15_5.h" /*A cycle in GF(2**4) generated by alpha=(x**4+x+1). It is extended an extra 16 entries to avoid some expensive mod operations.*/ static const unsigned char gf16_exp[31]={ 1,2,4,8,3,6,12,11,5,10,7,14,15,13,9,1,2,4,8,3,6,12,11,5,10,7,14,15,13,9,1 }; /*The location of each integer 1...16 in the cycle.*/ static const signed char gf16_log[16]={ -1,0,1,4,2,8,5,10,3,14,9,7,6,13,11,12 }; /*Multiplication in GF(2**4) using logarithms.*/ static unsigned gf16_mul(unsigned _a,unsigned _b){ return _a==0||_b==0?0:gf16_exp[gf16_log[_a]+gf16_log[_b]]; } /*Division in GF(2**4) using logarithms. The result when dividing by zero is undefined.*/ static unsigned gf16_div(unsigned _a,unsigned _b){ return _a==0?0:gf16_exp[gf16_log[_a]+15-gf16_log[_b]]; } /*Multiplication in GF(2**4) when the second argument is known to be non-zero (proven by representing it by its logarithm).*/ static unsigned gf16_hmul(unsigned _a,unsigned _logb){ return _a==0?0:gf16_exp[gf16_log[_a]+_logb]; } /*The syndrome normally has five values, S_1 ... S_5. We only calculate and store the odd ones in _s, since S_2=S_1**2 and S_4=S_2**2. Returns zero iff all the syndrome values are zero.*/ static int bch15_5_calc_syndrome(unsigned _s[3],unsigned _y){ unsigned p; int i; int j; p=0; for(i=0;i<15;i++)if(_y&1<0&&!_o[d-1];d--); return d; } /*Find the roots of the error polynomial. Returns the number of roots found, or a negative value if the polynomial did not have enough roots, indicating a decoding error.*/ static int bch15_5_calc_epos(unsigned _epos[3],unsigned _s[3]){ unsigned o[3]; int nerrors; int d; int i; d=bch15_5_calc_omega(o,_s); nerrors=0; if(d==1)_epos[nerrors++]=gf16_log[o[0]]; else if(d>0){ for(i=0;i<15;i++){ int i2; i2=gf16_log[gf16_exp[i<<1]]; if(!(gf16_exp[i+i2]^gf16_hmul(o[0],i2)^gf16_hmul(o[1],i)^o[2])){ _epos[nerrors++]=i; } } if(nerrors0){ /*If we had a non-zero syndrome value, we should always find at least one error location, or we've got a decoding error.*/ for(i=0;i>10)==y){ /*Decoding succeeded.*/ *_y=y; return nerrors; } } /*Decoding failed due to too many bit errors.*/ return -1; } unsigned bch15_5_encode(unsigned _x){ return (-(_x&1)&0x0537)^(-(_x>>1&1)&0x0A6E)^(-(_x>>2&1)&0x11EB)^ (-(_x>>3&1)&0x23D6)^(-(_x>>4&1)&0x429B); } #if 0 #include static unsigned codes[32]; static int hamming(int _a,int _b){ int d; int n; d=_a^_b; for(n=0;d;n++)d&=d-1; return n; } static int closest(int _y){ int min_i; int min_d; int i; int d; min_i=0; min_d=hamming(_y,codes[0]); for(i=1;i<32;i++){ d=hamming(_y,codes[i]); if(dFailed\n",i); if(hamming(i,z)<=3)printf("Error: 0x%04X should map to 0x%04X\n",i,z); } else{ printf("0x%04X->0x%04X\n",i,y); if(z!=y)printf("Error: 0x%04X should map to 0x%04X\n",i,z); } } return 0; } #endif