📄 bbsanc_php.htm
字号:
class=content>发信人: goloho (我想你), 信区: Commun <BR>标 题: rs编码的源程序。<BR>发信站: BBS 水木清华站 (Fri Jul 27 08:12:19 2001)<BR><BR>由于太多人向我索求rs程序,所以考虑再三还是把它贴出来,不过首先申明,此程序只<BR>作研究用!<BR>/* rs.c */<BR>/* This program is an encoder/decoder for Reed-Solomon codes. Encoding is in<BR><BR> systematic form, decoding via the Berlekamp iterative algorithm.<BR> In the present form , the constants mm, nn, tt, and kk=nn-2tt must be<BR> specified (the double letters are used simply to avoid clashes with<BR> other n,k,t used in other programs into which this was incorporated!)<BR> Also, the irreducible polynomial used to generate GF(2**mm) must also be<BR> entered -- these can be found in Lin and Costello, and also Clark and Cai<BR>n.<BR> The representation of the elements of GF(2**m) is either in index form,<BR> where the number is the power of the primitive element alpha, which is<BR> convenient for multiplication (add the powers modulo 2**m-1) or in<BR> polynomial form, where the bits represent the coefficients of the<BR> polynomial representation of the number, which is the most convenient for<BR>m<BR> for addition. The two forms are swapped between via lookup tables.<BR> This leads to fairly messy looking expressions, but unfortunately, there<BR> is no easy alternative when working with Galois arithmetic.<BR> The code is not written in the most elegant way, but to the best<BR> of my knowledge, (no absolute guarantees!), it works.<BR> However, when including it into a simulation program, you may want to do<BR> some conversion of global variables (used here because I am lazy!) to<BR> local variables where appropriate, and passing parameters (eg array<BR> addresses) to the functions may be a sensible move to reduce the number<BR> of global variables and thus decrease the chance of a bug being introduce<BR>d.<BR> This program does not handle erasures at present, but should not be hard<BR> to adapt to do this, as it is just an adjustment to the Berlekamp-Massey<BR> algorithm. It also does not attempt to decode past the BCH bound -- see<BR> Blahut "Theory and practice of error control codes" for how to do this.<BR> Simon Rockliff, University of Adelaide 21/9/89<BR> 26/6/91 Slight modifications to remove a compiler dependent bug which had<BR>n't<BR> previously surfaced. A few extra comments added for clarity.<BR> Appears to all work fine, ready for posting to net!<BR> Notice<BR> --------<BR> This program may be freely modified and/or given to whoever wants it.<BR> A condition of such distribution is that the author's contribution be<BR> acknowledged by his name being left in the comments heading the program,<BR> however no responsibility is accepted for any financial or other loss whi<BR>ch<BR> may result from some unforseen errors or malfunctioning of the program<BR> during use.<BR> Simon Rockliff, 26th June 1991<BR>*/<BR>#include <math.h><BR>#include <stdio.h><BR>#define mm 4 /* RS code over GF(2**4) - change to suit */<BR>#define nn 15 /* nn=2**mm -1 length of codeword */<BR>#define tt 3 /* number of errors that can be corrected */<BR>#define kk 9 /* kk = nn-2*tt */<BR>int pp [mm+1] = { 1, 1, 0, 0, 1} ; /* specify irreducible polynomial coeffts<BR> */<BR>int alpha_to [nn+1], index_of [nn+1], gg [nn-kk+1] ;<BR>int recd [nn], data [kk], bb [nn-kk] ;<BR>void generate_gf()<BR>/* generate GF(2**mm) from the irreducible polynomial p(X) in pp[0]..pp[mm]<BR> lookup tables: index->polynomial form alpha_to[] contains j=alpha**i;<BR> polynomial form -> index form index_of[j=alpha**i] = i<BR> alpha=2 is the primitive element of GF(2**mm)<BR>*/<BR> {<BR> register int i, mask ;<BR> mask = 1 ;<BR> alpha_to[mm] = 0 ;<BR> for (i=0; i<mm; i++)<BR> { alpha_to[i] = mask ;<BR> index_of[alpha_to[i]] = i ;<BR> if (pp[i]!=0)<BR> alpha_to[mm] ^= mask ;<BR> mask <<= 1 ;<BR> }<BR> index_of[alpha_to[mm]] = mm ;<BR> mask >>= 1 ;<BR> for (i=mm+1; i<nn; i++)<BR> { if (alpha_to[i-1] >= mask)<BR> alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1]^mask)<<1) ;<BR> else alpha_to[i] = alpha_to[i-1]<<1 ;<BR> index_of[alpha_to[i]] = i ;<BR> }<BR> index_of[0] = -1 ;<BR> for(i=0;i<5;i++)printf("gf%d is%d\n",i,alpha_to[i]);<BR> }<BR>void gen_poly()<BR>/* Obtain the generator polynomial of the tt-error correcting, length<BR> nn=(2**mm -1) Reed Solomon code from the product of (X+alpha**i), i=1..2*<BR>tt<BR>*/<BR> {<BR> register int i,j ;<BR> gg[0] = 2 ; /* primitive element alpha = 2 for GF(2**mm) */<BR> gg[1] = 1 ; /* g(x) = (X+alpha) initially */<BR> for (i=2; i<=nn-kk; i++)<BR> { gg[i] = 1 ;<BR> for (j=i-1; j>0; j--)<BR> if (gg[j] != 0) gg[j] = gg[j-1]^ alpha_to[(index_of[gg[j]]+i)%nn] ;<BR><BR> else gg[j] = gg[j-1] ;<BR> gg[0] = alpha_to[(index_of[gg[0]]+i)%nn] ; /* gg[0] can never be z<BR>ero */<BR> }<BR> /* convert gg[] to index form for quicker encoding */<BR> for (i=0; i<=nn-kk; i++) gg[i] = index_of[gg[i]] ;<BR> }<BR>void encode_rs()<BR>/* take the string of symbols in data[i], i=0..(k-1) and encode systematical<BR>ly<BR> to produce 2*tt parity symbols in bb[0]..bb[2*tt-1]<BR> data[] is input and bb[] is output in polynomial form.<BR> Encoding is done by using a feedback shift register with appropriate<BR> connections specified by the elements of gg[], which was generated above.<BR><BR> Codeword is c(X) = data(X)*X**(nn-kk)+ b(X) */<BR> {<BR> register int i,j ;<BR> int feedback ;<BR> for (i=0; i<nn-kk; i++) bb[i] = 0 ;<BR> for (i=kk-1; i>=0; i--)<BR> { feedback = index_of[data[i]^bb[nn-kk-1]] ;<BR> if (feedback != -1)<BR> { for (j=nn-kk-1; j>0; j--)<BR> if (gg[j] != -1)<BR> bb[j] = bb[j-1]^alpha_to[(gg[j]+feedback)%nn] ;<BR> else<BR> bb[j] = bb[j-1] ;<BR> bb[0] = alpha_to[(gg[0]+feedback)%nn] ;<BR> }<BR> else<BR> { for (j=nn-kk-1; j>0; j--)<BR> bb[j] = bb[j-1] ;<BR> bb[0] = 0 ;<BR> } ;<BR> } ;<BR> } ;<BR>void decode_rs()<BR>/* assume we have received bits grouped into mm-bit symbols in recd[i],<BR> i=0..(nn-1), and recd[i] is index form (ie as powers of alpha).<BR> We first compute the 2*tt syndromes by substituting alpha**i into rec(X) <BR>and<BR> evaluating, storing the syndromes in s[i], i=1..2tt (leave s[0] zero) .<BR> Then we use the Berlekamp iteration to find the error location polynomial<BR><BR> elp[i]. If the degree of the elp is >tt, we cannot correct all the erro<BR>rs<BR> and hence just put out the information symbols uncorrected. If the degree<BR> of<BR> elp is <=tt, we substitute alpha**i , i=1..n into the elp to get the root<BR>s,<BR> hence the inverse roots, the error location numbers. If the number of err<BR>ors<BR> located does not equal the degree of the elp, we have more than tt errors<BR><BR> and cannot correct them. Otherwise, we then solve for the error value at<BR><BR> the error location and correct the error. The procedure is that found in<BR><BR> Lin and Costello. For the cases where the number of errors is known to be<BR> too<BR> large to correct, the information symbols as received are output (the<BR> advantage of systematic encoding is that hopefully some of the informatio<BR>n<BR> symbols will be okay and that if we are in luck, the errors are in the<BR> parity part of the transmitted codeword). Of course, these insoluble cas<BR>es<BR> can be returned as error flags to the calling routine if desired. */<BR> {<BR> register int i,j,u,q ;<BR> int elp[nn-kk+2][nn-kk], d[nn-kk+2], l[nn-kk+2], u_lu[nn-kk+2], s[nn-kk+1<BR>] ;<BR> int count=0, syn_error=0, root[tt], loc[tt], z[tt+1], err[nn], reg[tt+1] <BR>;<BR>/* first form the syndromes */<BR> for (i=1; i<=nn-kk; i++)<BR> { s[i] = 0 ;<BR> for (j=0; j<nn; j++)<BR> if (recd[j]!=-1)<BR> s[i] ^= alpha_to[(recd[j]+i*j)%nn] ; /* recd[j] in index form<BR> */<BR>/* convert syndrome from polynomial form to index form */<BR> if (s[i]!=0) syn_error=1 ; /* set flag if non-zero syndrome =><BR> error */<BR> s[i] = index_of[s[i]] ;<BR> } ;<BR> if (syn_error) /* if errors, try and correct */<BR> {<BR>/* compute the error location polynomial via the Berlekamp iterative algorit<BR>hm,<BR> following the terminology of Lin and Costello : d[u] is the 'mu'th<BR> discrepancy, where u='mu'+1 and 'mu' (the Greek letter!) is the step numb<BR>er<BR> ranging from -1 to 2*tt (see L&C), l[u] is the<BR> degree of the elp at that step, and u_l[u] is the difference between the<BR> step number and the degree of the elp.<BR>*/<BR>/* initialise table entries */<BR> d[0] = 0 ; /* index form */<BR> d[1] = s[1] ; /* index form */<BR> elp[0][0] = 0 ; /* index form */<BR> elp[1][0] = 1 ; /* polynomial form */<BR> for (i=1; i<nn-kk; i++)<BR> { elp[0][i] = -1 ; /* index form */<BR> elp[1][i] = 0 ; /* polynomial form */<BR> }<BR> l[0] = 0 ;<BR> l[1] = 0 ;<BR> u_lu[0] = -1 ;<BR> u_lu[1] = 0 ;<BR> u = 0 ;<BR> do<BR> {<BR> u++ ;<BR> if (d[u]==-1)<BR> { l[u+1] = l[u] ;<BR> for (i=0; i<=l[u]; i++)<BR> { elp[u+1][i] = elp[u][i] ;<BR> elp[u][i] = index_of[elp[u][i]] ;<BR> }<BR> }<BR> else<BR>/* search for words with greatest u_lu[q] for which d[q]!=0 */<BR> { q = u-1 ;<BR> while ((d[q]==-1) && (q>0)) q-- ;<BR>/* have found first non-zero d[q] */<BR> if (q>0)<BR> { j=q ;<BR> do<BR> { j-- ;<BR> if ((d[j]!=-1) && (u_lu[q]<u_lu[j]))<BR> q = j ;<BR> }while (j>0) ;<BR> } ;<BR>/* have now found q such that d[u]!=0 and u_lu[q] is maximum */<BR>/* store degree of new elp polynomial */<BR> if (l[u]>l[q]+u-q) l[u+1] = l[u] ;<BR> else l[u+1] = l[q]+u-q ;<BR>/* form new elp(x) */<BR> for (i=0; i<nn-kk; i++) elp[u+1][i] = 0 ;<BR> for (i=0; i<=l[q]; i++)<BR> if (elp[q][i]!=-1)<BR> elp[u+1][i+u-q] = alpha_to[(d[u]+nn-d[q]+elp[q][i])%nn] ;<BR> for (i=0; i<=l[u]; i++)<BR> { elp[u+1][i] ^= elp[u][i] ;<BR> elp[u][i] = index_of[elp[u][i]] ; /*convert old elp value t<BR>o index*/<BR> }<BR> }<BR> u_lu[u+1] = u-l[u+1] ;<BR>/* form (u+1)th discrepancy */<BR> if (u<nn-kk) /* no discrepancy computed on last iteration */<BR> {<BR> if (s[u+1]!=-1)<BR> d[u+1] = alpha_to[s[u+1]] ;<BR> else<BR> d[u+1] = 0 ;<BR> for (i=1; i<=l[u+1]; i++)<BR> if ((s[u+1-i]!=-1) && (elp[u+1][i]!=0))<BR> d[u+1] ^= alpha_to[(s[u+1-i]+index_of[elp[u+1][i]])%nn] ;<BR> d[u+1] = index_of[d[u+1]] ; /* put d[u+1] into index form */<BR> }<BR> } while ((u<nn-kk) && (l[u+1]<=tt)) ;<BR> u++ ;<BR> if (l[u]<=tt) /* can correct error */<BR> {<BR>/* put elp into index form */<BR> for (i=0; i<=l[u]; i++) elp[u][i] = index_of[elp[u][i]] ;<BR>/* find roots of the error location polynomial */<BR> for (i=1; i<=l[u]; i++)<BR> reg[i] = elp[u][i] ;<BR> count = 0 ;<BR> for (i=1; i<=nn; i++)<BR> { q = 1 ;<BR> for (j=1; j<=l[u]; j++)<BR> if (reg[j]!=-1)<BR> { reg[j] = (reg[j]+j)%nn ;<BR> q ^= alpha_to[reg[j]] ;<BR> } ;<BR> if (!q) /* store root and error location number indices <BR>*/<BR> { root[count] = i;<BR> loc[count] = nn-i ;<BR> count++ ;<BR> };<BR> } ;<BR> if (count==l[u]) /* no. roots = degree of elp hence <= tt errors<BR> */<BR> {<BR>/* form polynomial z(x) */<BR> for (i=1; i<=l[u]; i++) /* Z[0] = 1 always - do not need *<BR>/<BR> { if ((s[i]!=-1) && (elp[u][i]!=-1))<BR> z[i] = alpha_to[s[i]] ^ alpha_to[elp[u][i]] ;<BR> else if ((s[i]!=-1) && (elp[u][i]==-1))<BR> z[i] = alpha_to[s[i]] ;<BR> else if ((s[i]==-1) && (elp[u][i]!=-1))<BR> z[i] = alpha_to[elp[u][i]] ;<BR> else<BR> z[i] = 0 ;<BR> for (j=1; j<i; j++)<BR> if ((s[j]!=-1) && (elp[u][i-j]!=-1))<BR> z[i] ^= alpha_to[(elp[u][i-j] + s[j])%nn] ;<BR> z[i] = index_of[z[i]] ; /* put into index form */<BR> } ;<BR> /* evaluate errors at locations given by error location numbers loc[i] */<BR> for (i=0; i<nn; i++)<BR> { err[i] = 0 ;<BR> if (recd[i]!=-1) /* convert recd[] to polynomial form <BR>*/<BR> recd[i] = alpha_to[recd[i]] ;<BR> else recd[i] = 0 ;<BR> }<BR> for (i=0; i<l[u]; i++) /* compute numerator of error term firs<BR>t */<BR> { err[loc[i]] = 1; /* accounts for z[0] */<BR> for (j=1; j<=l[u]; j++)<BR> if (z[j]!=-1)<BR> err[loc[i]] ^= alpha_to[(z[j]+j*root[i])%nn] ;<BR> if (err[loc[i]]!=0)<BR> { err[loc[i]] = index_of[err[loc[i]]] ;<BR> q = 0 ; /* form denominator of error term */<BR> for (j=0; j<l[u]; j++)<BR> if (j!=i)<BR> q += index_of[1^alpha_to[(loc[j]+root[i])%nn]] ;<BR> q = q % nn ;<BR> err[loc[i]] = alpha_to[(err[loc[i]]-q+nn)%nn] ;<BR> recd[loc[i]] ^= err[loc[i]] ; /*recd[i] must be in polynom<BR>ial form */<BR> }<BR> }<BR> }<BR> else /* no. roots != degree of elp => >tt errors and cannot solv<BR>e */<BR> for (i=0; i<nn; i++) /* could return error flag if desired<BR> */<BR> if (recd[i]!=-1) /* convert recd[] to polynomial form <BR>*/<BR> recd[i] = alpha_to[recd[i]] ;<BR> else recd[i] = 0 ; /* just output received codeword as i<BR>s */<BR> }<BR> else /* elp has degree has degree >tt hence cannot solve */<BR> for (i=0; i<nn; i++) /* could return error flag if desired */<BR> if (recd[i]!=-1) /* convert recd[] to polynomial form */<BR> recd[i] = alpha_to[recd[i]] ;<BR> else recd[i] = 0 ; /* just output received codeword as is */<BR> }<BR> else /* no non-zero syndromes => no errors: output received codewor<BR>d */<BR> for (i=0; i<nn; i++)<BR> if (recd[i]!=-1) /* convert recd[] to polynomial form */<BR> recd[i] = alpha_to[recd[i]] ;<BR> else recd[i] = 0 ;<BR> }<BR>main()<BR>{<BR> register int i;<BR>/* generate the Galois Field GF(2**mm) */<BR> generate_gf() ;<BR> printf("Look-up tables for GF(2**%2d)\n",mm) ;<BR> printf(" i alpha_to[i] index_of[i]\n") ;<BR> for (i=0; i<=nn; i++)<BR> printf("%3d %3d %3d\n",i,alpha_to[i],index_of[i]) ;<BR> printf("\n\n") ;<BR>/* compute the generator polynomial for this RS code */<BR> gen_poly() ;<BR>/* for known data, stick a few numbers into a zero codeword. Data is in<BR> polynomial form.<BR>*/<BR>for (i=0; i<kk; i++) data[i] = 0 ;<BR>/* for example, say we transmit the following message (nothing special!) */<BR>data[0] = 8 ;<BR>data[1] = 6 ;<BR>data[2] = 8 ;<BR>data[3] = 1 ;<BR>data[4] = 2 ;<BR>data[5] = 4 ;<BR>data[6] = 15 ;<BR>data[7] = 9 ;<BR>data[8] = 9 ;<BR>/* encode data[] to produce parity in bb[]. Data input and parity output<BR> is in polynomial form<BR>*/<BR> encode_rs() ;<BR>/* put the transmitted codeword, made up of data plus parity, in recd[] */<BR> for (i=0; i<nn-kk; i++) recd[i] = bb[i] ;<BR> for (i=0; i<kk; i++) recd[i+nn-kk] = data[i] ;<BR>/* if you want to test the program, corrupt some of the elements of recd[]<BR> here. This can also be done easily in a debugger. */<BR>/* Again, lets say that a middle element is changed */<BR> data[nn-nn/2] = 3 ;<BR> for (i=0; i<nn; i++)<BR> recd[i] = index_of[recd[i]] ; /* put recd[i] into index form *<BR>/<BR>/* decode recv[] */<BR> decode_rs() ; /* recd[] is returned in polynomial form */<BR>/* print out the relevant stuff - initial and decoded {parity and message} *<BR>/<BR> printf("Results for Reed-Solomon code (n=%3d, k=%3d, t= %3d)\n\n",nn,kk,tt<BR>) ;<BR> printf(" i data[i] recd[i](decoded) (data, recd in polynomial form)\<BR>n");<BR> for (i=0; i<nn-kk; i++)<BR> printf("%3d %3d %3d\n",i, bb[i], recd[i]) ;<BR> for (i=nn-kk; i<nn; i++)<BR> printf("%3d %3d %3d\n",i, data[i-nn+kk], recd[i]) ;<BR>}<BR><BR><BR>--<BR><BR>※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.119.230.80]<BR></FONT></TD></TR></TBODY></TABLE></CENTER>
<TABLE cellSpacing=0 cellPadding=3 width="100%" border=0>
<TBODY>
<TR>
<TD background=bbsanc_php.files/dashed.gif colSpan=2 height=9></TD></TR>
<TR>
<TD class=b1 align=middle colSpan=2>[<A
href="http://www.smth.edu.cn/bbsanc.php?path=%2Fgroups%2Fsci.faq%2FCommun%2Fforum%2Fsimmu%2FC%2Frs#listtop">返回顶部</A>]
[<A href="javascript:location.reload()">刷新</A>] [<A
href="http://www.smth.edu.cn/bbsodoc.php?board=Commun">同主题模式</A>] [<A
href="http://www.smth.edu.cn/bbsdoc.php?board=Commun">普通模式</A>] [<A
href="http://www.smth.edu.cn/bbsbfind.php?board=Commun">版内查询</A>]
</TD></TR></TBODY></TABLE>
<P align=center>[<A
href="http://www.smth.edu.cn/bbssfav.php?act=choose&title=%BE%AB%BB%AA%C7%F8&url=%2Fbbsanc.php%3Fpath%3D%252Fgroups%252Fsci.faq%252FCommun%252Fforum%252Fsimmu%252FC%252Frs&type=0">我的百宝箱</A>]
[<A href="http://www.smth.edu.cn/mainpage.php">返回首页</A>] [<A
href="http://www.smth.edu.cn/bbs0an.php?path=%2Fgroups%2Fsci.faq%2FCommun%2Fforum%2Fsimmu%2FC">上级目录</A>]
[<A href="http://www.smth.edu.cn/bbs0an.php">根目录</A>] [<A
href="http://www.smth.edu.cn/bbsxsearch.php">令狐冲精华区搜索</A>] [<A
href="http://www.smth.edu.cn/bbsanc.php?path=%2Fgroups%2Fsci.faq%2FCommun%2Fforum%2Fsimmu%2FC%2Frs#listtop">返回顶部</A>]
[<A href="javascript:location.reload()">刷新</A>] [<A
href="javascript:history.go(-1)">返回</A>] </P></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -