Reed Solomon (リード ソロモン符号)を実装する (C#版) - C#

C#でのReed Solomon(リード ソロモン符号)の実装のコードの紹介です。

概要

Reed Solomon(リード ソロモン符号)を実装します。
今回は実装のみで理論の解説はありません。
また、コードも流用コードを含みます。
Delphi版の実装を移植したものとなります
使い方はこちら

参考・出展

こちらを参考にしております。理論などの解説も下記書籍からどうぞ。

コード

こちらのデモを動作させる場合は、下記 iPentecReedSolomon.cs のみで実行できます。
iPentecReedSolomon.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iPentec.ReedSolomonCodec
{
  public class iPentecReedSolomon
  {
    //public static object[] pPP = new object[16 + 1];
    public static byte[][] pPP = new byte[16 + 1][];

    public const int DEFAULT_MM = 8;
    public const int DEFAULT_NP = 32;

    // ガロア体原始多項式
    public static byte[] PP2 = { 1, 1, 1 };
    public static byte[] PP3 = { 1, 1, 0, 1 };        // 1 + x + x^3
    public static byte[] PP4 = { 1, 1, 0, 0, 1 };        // 1 + x + x^4
    public static byte[] PP5 = { 1, 0, 1, 0, 0, 1 };        // 1 + x^2 + x^5
    public static byte[] PP6 = { 1, 1, 0, 0, 0, 0, 1 };        // 1 + x + x^6
    public static byte[] PP7 = { 1, 0, 0, 1, 0, 0, 0, 1 };        // 1 + x^3 + x^7
    public static byte[] PP8 = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };        // 1+x^2+x^3+x^4+x^8
    public static byte[] PP9 = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };        // 1+x^4+x^9
    public static byte[] PP10 = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^3+x^10
    public static byte[] PP11 = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^2+x^11
    public static byte[] PP12 = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };        // 1+x+x^4+x^6+x^12
    public static byte[] PP13 = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^3+x^4+x^13
    public static byte[] PP14 = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };        // 1+x+x^6+x^10+x^14
    public static byte[] PP15 = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^15
    public static byte[] PP16 = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };        // 1+x+x^3+x^12+x^16


    private int FGFDimension = 0;
    private int FRSLength = 0;
    private int FDataLength = 0;
    private int FParityLength = 0;
    private int FMaxRSLength = 0;
    private byte[] PP = new byte[16 + 1];

    // specify irreducible polynomial coeffts
    // ガロア体原始多項式
    private short[] ExpToVector;
    // alpha to
    private short[] VectorToExp;
    // index of
    private short[] gg;
    // 誤り訂正生成多項式
    private short[] bb;
    private short[] data;
    private short[] recd;
    private byte[] CodeWord;


    public int DataLength
    {
      get
      {
        return FDataLength;
      }
    }
   
    public iPentecReedSolomon()
    {
      pPP[2] = PP2;
      pPP[3] = PP3;
      pPP[4] = PP4;
      pPP[5] = PP5;
      pPP[6] = PP6;
      pPP[7] = PP7;
      pPP[8] = PP8;
      pPP[9] = PP9;
      pPP[10] = PP10;
      pPP[11] = PP11;
      pPP[12] = PP12;
      pPP[13] = PP13;
      pPP[14] = PP14;
      pPP[15] = PP15;
      pPP[16] = PP16;

      InitBuffers();
      // Clear the internal buffers
      // generate the Galois Field GF(2**mm)
      // Generate_gf(DEFAULT_MM);
      // FGFDimension:=DEFAULT_MM;
      InitParameters(DEFAULT_MM, DEFAULT_NP);
    }

    public iPentecReedSolomon(int GFDimension, int ParityLength)
    {
      pPP[2] = PP2;
      pPP[3] = PP3;
      pPP[4] = PP4;
      pPP[5] = PP5;
      pPP[6] = PP6;
      pPP[7] = PP7;
      pPP[8] = PP8;
      pPP[9] = PP9;
      pPP[10] = PP10;
      pPP[11] = PP11;
      pPP[12] = PP12;
      pPP[13] = PP13;
      pPP[14] = PP14;
      pPP[15] = PP15;
      pPP[16] = PP16;

      InitBuffers();
      InitParameters(GFDimension, ParityLength);
    }

    public void dispose()
    {
      /*
      this.Finalize(gg);
      this.Finalize(bb);
      this.Finalize(data);
      this.Finalize(ExpToVector);
      this.Finalize(VectorToExp);
      this.Finalize(CodeWord);
      this.Finalize(recd);
      base.Destroy();
      */
    }

    private void InitParameters(int GFDimension, int ParityLength)
    {
      FGFDimension = GFDimension;
      FParityLength = ParityLength;
      FMaxRSLength = (1 << FGFDimension) - 1; // nn=2**mm -1   Max length of codeword
      FRSLength = (1 << FGFDimension) - 1;    // nn=2**mm -1   Max length of codeword
      FDataLength = FRSLength - FParityLength;// data symbols, kk = nn-2*MaxErrors

      gg = new short[FParityLength + 1];
      bb = new short[FParityLength - 1 + 1];
      data = new short[FDataLength + 1];

      ExpToVector = new short[FRSLength + 1];
      VectorToExp = new short[FRSLength + 1];
      CodeWord = new byte[FRSLength - 1 + 1];
      recd = new short[FRSLength - 1 + 1];

      Generate_GF(FGFDimension);
      gen_poly();
    }

    private void ReInitParameters(int GFDimension, int ParityLength, int RSLength)
    {
      FGFDimension = GFDimension;
      FParityLength = ParityLength;
      FMaxRSLength = (1 << FGFDimension) - 1;        // nn=2**mm -1   Max length of codeword
      FRSLength = RSLength;
      FDataLength = FRSLength - FParityLength;       // data symbols, kk = nn-2*MaxErrors

      gg = new short[FParityLength + 1];
      bb = new short[FParityLength - 1 + 1];
      data = new short[FDataLength + 1];

      ExpToVector = new short[FMaxRSLength + 1];
      VectorToExp = new short[FMaxRSLength + 1];
      CodeWord = new byte[FRSLength - 1 + 1];
      recd = new short[FRSLength - 1 + 1];

      Generate_GF(FGFDimension);
      gen_poly();
    }

    protected void Generate_GF(int mm)
    {
      int i;
      short mask;
      SetPrimitive(ref PP, mm);
      mask = 1;
      ExpToVector[mm] = 0;
      for (i = 0; i <= (mm - 1); i++) {
        ExpToVector[i] = mask;
        VectorToExp[ExpToVector[i]] = (short)i;
        if (PP[i] != 0) {
          ExpToVector[mm] = (short)(ExpToVector[mm] ^ mask);
        }
        mask = (short)(mask << 1);
      }
      VectorToExp[ExpToVector[mm]] = (short)mm;
      mask = (short)(mask >> 1);
      for (i = (mm + 1); i <= (FRSLength - 1); i++) {
        if (ExpToVector[i - 1] >= mask) {
          ExpToVector[i] = (short)(ExpToVector[mm] ^ ((ExpToVector[i - 1] ^ mask) << 1));
        }
        else {
          ExpToVector[i] = (short)(ExpToVector[i - 1] << 1);
        }
        VectorToExp[ExpToVector[i]] = (short)i;
      }
      VectorToExp[0] = -1;
    }

    protected void gen_poly()
    {
      short i;
      short j;
      gg[0] = 2;
      // primitive element alpha = 2  for GF(2**mm)
      gg[1] = 1;
      // g(x) = (X+alpha) initially
      for (i = 2; i <= (FRSLength - FDataLength); i++) {
        gg[i] = 1;
        for (j = (short)(i - 1); j >= 1; j--) {
          if ((gg[j] != 0)) {
            gg[j] = (short)(gg[j - 1] ^ ExpToVector[(VectorToExp[gg[j]] + i) % FMaxRSLength]);
          }
          else {
            gg[j] = gg[j - 1];
          }
        }
        // gg[0] can never be zero
        gg[0] = ExpToVector[(VectorToExp[gg[0]] + i) % FMaxRSLength];
      }
      // Convert gg[] to index form for quicker encoding.
      for (i = 0; i <= FParityLength; i++) {
        gg[i] = VectorToExp[gg[i]];
      }
    }

    protected void SetPrimitive(ref byte[] PP, int nIdx)
    {
      //@ Unsupported function or procedure: 'Move'
      // Move(Units.iPentecReedSolomon.pPP[nIdx], PP, (nIdx + 1));
      //Array.Copy(pPP, nIdx, PP, 0, nIdx+1);
      //Array.Copy(pPP[nIdx], 0, PP, 0, nIdx+1);
      for (int i = 0; i < nIdx + 1; i++) {
        PP[i] = pPP[nIdx][i];
      }
    }

    // TReedSolomon.InitBuffers
    public void InitBuffers()
    {
      /*
        //@ Unsupported function or procedure: 'FillChar'
        FillChar(data, sizeof(data), 0);
        //@ Unsupported function or procedure: 'FillChar'
        FillChar(recd, sizeof(recd), 0);
        //@ Unsupported function or procedure: 'FillChar'
        FillChar(CodeWord, sizeof(CodeWord), 0);
       */
      if (data != null) {
        for (int i = 0; i < data.Length; i++) {
          data[i] = 0;
        }
      }
      if (recd != null) {
        for (int i = 0; i < recd.Length; i++) {
          recd[i] = 0;
        }
      }
      if (CodeWord != null) {
        for (int i = 0; i < CodeWord.Length; i++) {
          CodeWord[i] = 0;
        }
      }
    }

    public void EncodeRS(ref byte[] xData, ref byte[] xEncoded)
    {
      //int e;
      byte[] rswork = new byte[123 - 1 + 1];
      // RS符号計算用作業領域
      int nI;
      int i;
      int j;
      short feedback;
      //byte[] axData;

      for (i = 0; i < bb.Length; i++) {
        bb[i] = 0;
      }
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        //data[nI] = axData[nI];
        data[nI] = xData[nI];
      }
      for (i = (FDataLength - 1); i >= 0; i--) {
        feedback = VectorToExp[data[i] ^ bb[FParityLength - 1]];
        if ((feedback != -1)) {
          for (j = (FParityLength - 1); j >= 1; j--) {
            if ((gg[j] != -1)) {
              bb[j] = (short)(bb[j - 1] ^ ExpToVector[(gg[j] + feedback) % FMaxRSLength]);
            }
            else {
              bb[j] = bb[j - 1];
            }
          }
          bb[0] = ExpToVector[(gg[0] + feedback) % FMaxRSLength];
        }
        else {
          for (j = (FParityLength - 1); j >= 1; j--) {
            bb[j] = bb[j - 1];
          }
          bb[0] = 0;
        }
      }
      // put the transmitted codeword, made up of data
      // plus parity, in CodeWord
      for (nI = 0; nI <= (FParityLength - 1); nI++) {
        recd[nI] = bb[nI];
      }
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        recd[nI + FParityLength] = data[nI];
      }
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        CodeWord[nI] = (byte)recd[nI];
      }

      //@ Unsupported function or procedure: 'Move'
      //Move(CodeWord[0], xEncoded, FRSLength);
      Array.Copy(CodeWord, 0, xEncoded, 0, FRSLength);
    }

    public void EncodeRSEx(ref byte[] xData, ref byte[] xEncoded, ref byte[] xParity)
    {
      int nI;
      int i;
      int j;
      short feedback;
      int e;
      short[] invertgg;
      invertgg = new short[gg.Length];
      for (i = 0; i < gg.Length; i++) {
        //invertgg[i] = gg[gg.Length - 1 - 1 - i];
        invertgg[i] = gg[gg.Length - 1 - i];
      }
      for (i = 0; i < bb.Length; i++) {
        bb[i] = 0;
      }
      //for (nI = 0; nI <= (FRSLength - 1); nI++) {

      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        data[nI] = xData[nI];
      }
      for (i = (FDataLength - 1); i >= 0; i--) {
        feedback = VectorToExp[data[i] ^ bb[FParityLength - 1]];
        if ((feedback != -1)) {
          for (j = (FParityLength - 1); j >= 1; j--) {
            if ((gg[j] != -1)) {
              bb[j] = (short)(bb[j - 1] ^ ExpToVector[(gg[j] + feedback) % FMaxRSLength]);
            }
            else {
              bb[j] = bb[j - 1];
            }
          }
          bb[0] = ExpToVector[(gg[0] + feedback) % FMaxRSLength];
        }
        else {
          for (j = (FParityLength - 1); j >= 1; j--) {
            bb[j] = bb[j - 1];
          }
          bb[0] = 0;
        }
      }
      // put the transmitted codeword, made up of data
      // plus parity, in CodeWord
      for (nI = 0; nI <= (FParityLength - 1); nI++) {
        recd[nI] = bb[nI];
        xParity[nI] = (byte)bb[nI];
      }
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        recd[nI + FParityLength] = data[nI];
      }
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        CodeWord[nI] = (byte)recd[nI];
      }
      //@ Unsupported function or procedure: 'Move'
      //Move(CodeWord[0], xEncoded, FRSLength);
      Array.Copy(CodeWord, 0, xEncoded, 0, FRSLength);
    }

    //public int DecodeRS(ref object xData, ref object xDecoded)
    public int DecodeRS(ref byte[] xData, ref byte[] xDecoded)
    {
      int result;
      //byte[] axData;
      //byte[] axDecoded;
      //string cStr;
      int nI;
      int nJ;
      int nK;
      int i;
      int j;
      short u;
      short q;
      short[][] elp;            // Array[0..np+1 , 0..np - 1] of smallint ;
      short[] d;            // Array[0..np+1] of smallint ;
      short[] l;            // Array[0..np+1] of smallint ;
      short[] u_lu;            // Array[0..np+1] of smallint ;
      short[] s;            // Array[0..np]   of smallint ;
      short count;
      short syn_error;
      int lpc;
      short[] root;            // Array[0..MaxErrors - 1] of smallint ;
      short[] loc;            // Array[0..MaxErrors - 1] of smallint ;
      short[] z;            // Array[0..MaxErrors]     of smallint ;
      short[] err;            // Array[0..nn-1]          of smallint ;
      short[] reg;            // Array[0..MaxErrors]     of smallint ;
      // DecodeRS

      elp = new short[FParityLength + 1 + 1][];
      for (lpc = 0; lpc < elp.Length; lpc++) {
        //@ Unsupported function or procedure: 'SetLength'
        //elp[lpc].Length = FParityLength - 1 + 1;
        elp[lpc] = new short[FParityLength - 1 + 1];
      }

      d = new short[FParityLength + 1 + 1];
      l = new short[FParityLength + 1 + 1];
      u_lu = new short[FParityLength + 1 + 1];
      s = new short[FParityLength + 1];
      root = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      loc = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      z = new short[Convert.ToInt64(FParityLength / 2) + 1];
      err = new short[FRSLength - 1 + 1];
      reg = new short[Convert.ToInt64(FParityLength / 2) + 1];
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        //recd[nI] = axData[nI];
        recd[nI] = xData[nI];
      }
      for (i = 0; i <= (FRSLength - 1); i++) {
        recd[i] = VectorToExp[recd[i]];
      }
      // put recd[i] into index form
      count = 0;
      syn_error = 0;
      result = 0;
      // first form the syndromes
      for (i = 1; i <= FParityLength; i++) {
        s[i] = 0;
        for (j = 0; j <= (FRSLength - 1); j++) {
          if (recd[j] != -1) {
            // recd[j] in index form
            s[i] = (short)(s[i] ^ ExpToVector[(recd[j] + i * j) % FMaxRSLength]);
          }
        }
        // convert syndrome from polynomial form to index form
        if ((s[i] != 0)) {
          syn_error = 1;
          // set flag if non-zero syndrome => error
        }
        s[i] = VectorToExp[s[i]];
      }
      if (syn_error != 0) {
        d[0] = 0;
        // index form
        d[1] = s[1];
        // index form
        elp[0][0] = 0;
        // index form
        elp[1][0] = 1;
        // polynomial form
        for (i = 1; i <= (FParityLength - 1); i++) {
          elp[0][i] = -1;
          // index form
          elp[1][i] = 0;
          // polynomial form
        }
        l[0] = 0;
        l[1] = 0;
        u_lu[0] = -1;
        u_lu[1] = 0;
        u = 0;
        while (((u < FParityLength) && (l[u + 1] <= Convert.ToInt64(FParityLength / 2)))) {
          u++;
          if ((d[u] == -1)) {
            l[u + 1] = l[u];
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = elp[u][i];
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          else {
            // search for words with greatest u_lu[q] for which d[q]!=0
            q = (short)(u - 1);
            while (((d[q] == -1) && (q > 0))) {
              q -= 1;
            }
            // have found first non-zero d[q]
            if ((q > 0)) {
              j = q;
              while (j > 0) {
                j -= 1;
                if (((d[j] != -1) && (u_lu[q] < u_lu[j]))) {
                  q = (short)j;
                }
              }
            }
            // have now found q such that d[u]!=0 and u_lu[q] is maximum
            // store degree of new elp polynomial
            if ((l[u] > l[q] + u - q)) {
              l[u + 1] = l[u];
            }
            else {
              l[u + 1] = (short)(l[q] + u - q);
            }
            // form new elp(x)
            for (i = 0; i <= (FParityLength - 1); i++) {
              elp[u + 1][i] = 0;
            }
            for (i = 0; i <= l[q]; i++) {
              // if (elp[q][i] <> -1) then elp[u+1][i+u-q] := ExpToVector[(d[u] + FRSLength - d[q] + elp[q][i]) mod FMaxRSLength] ;
              if ((elp[q][i] != -1)) {
                elp[u + 1][i + u - q] = ExpToVector[(d[u] + FMaxRSLength - d[q] + elp[q][i]) % FMaxRSLength];
              }
            }
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = (short)(elp[u + 1][i] ^ elp[u][i]);
              // convert old elp value to index
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          u_lu[u + 1] = (short)(u - l[u + 1]);
          // form (u+1)th discrepancy
          if (u < FParityLength) {
            // no discrepancy computed on last iteration
            if ((s[u + 1] != -1)) {
              d[u + 1] = ExpToVector[s[u + 1]];
            }
            else {
              d[u + 1] = 0;
            }
            for (i = 1; i <= l[u + 1]; i++) {
              if (((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0))) {
                d[u + 1] = (short)(d[u + 1] ^ ExpToVector[(s[u + 1 - i] + VectorToExp[elp[u + 1][i]]) % FMaxRSLength]);
              }
            }
            // put d[u+1] into index form
            d[u + 1] = VectorToExp[d[u + 1]];
          }
        }
        // end While
        u++;
        if (l[u] <= Convert.ToInt64(FParityLength / 2)) {
          // can correct error
          // put elp into index form
          for (i = 0; i <= l[u]; i++) {
            elp[u][i] = VectorToExp[elp[u][i]];
          }
          // find roots of the error location polynomial
          for (i = 1; i <= l[u]; i++) {
            reg[i] = elp[u][i];
          }
          // for i := 1 to FRSLength do begin
          for (i = 1; i <= FMaxRSLength; i++) {
            q = 1;
            for (j = 1; j <= l[u]; j++) {
              if (reg[j] != -1) {
                reg[j] = (short)((reg[j] + j) % FMaxRSLength);
                q = (short)(q ^ ExpToVector[reg[j]]);
              }
            }
            if (q == 0) {
              // store root and error location number indices
              root[count] = (short)i;
              // loc[count] := FRSLength - i ;
              loc[count] = (short)(FMaxRSLength - i);
              count++;
            }
          }
          if (count == l[u]) {
            // no. roots = degree of elp hence <= tt errors
            result = count;
            // form polynomial z(x)
            for (i = 1; i <= l[u]; i++) {
              // Z[0] = 1 always - do not need
              if (((s[i] != -1) && (elp[u][i] != -1))) {
                z[i] = (short)(ExpToVector[s[i]] ^ ExpToVector[elp[u][i]]);
              }
              else if (((s[i] != -1) && (elp[u][i] == -1))) {
                z[i] = ExpToVector[s[i]];
              }
              else if (((s[i] == -1) && (elp[u][i] != -1))) {
                z[i] = ExpToVector[elp[u][i]];
              }
              else {
                z[i] = 0;
              }
              for (j = 1; j <= (i - 1); j++) {
                if (((s[j] != -1) && (elp[u][i - j] != -1))) {
                  z[i] = (short)(z[i] ^ ExpToVector[(elp[u][i - j] + s[j]) % FMaxRSLength]);
                }
              }
              // put into index form
              z[i] = VectorToExp[z[i]];
            }
            // evaluate errors at locations given by
            // error location numbers loc[i]
            for (i = 0; i <= (FRSLength - 1); i++) {
              // for i := 0 to (FMaxRSLength - 1) do begin
              err[i] = 0;
              // convert recd[] to polynomial form
              if (recd[i] != -1) {
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
            }
            for (i = 0; i <= (l[u] - 1); i++) {
              // compute numerator of error term first
              err[loc[i]] = 1;
              // accounts for z[0]
              for (j = 1; j <= l[u]; j++) {
                if (z[j] != -1) {
                  err[loc[i]] = (short)(err[loc[i]] ^ ExpToVector[(z[j] + j * root[i]) % FMaxRSLength]);
                }
              }
              if (err[loc[i]] != 0) {
                err[loc[i]] = VectorToExp[err[loc[i]]];
                q = 0;
                // form denominator of error term
                for (j = 0; j <= (l[u] - 1); j++) {
                  if (j != i) {
                    q = (short)(q + VectorToExp[1 ^ ExpToVector[(loc[j] + root[i]) % FMaxRSLength]]);
                  }
                }
                q = (short)(q % FMaxRSLength);
                // err[loc[i]] := ExpToVector[(err[loc[i]] - q + FRSLength) mod FMaxRSLength] ;
                err[loc[i]] = ExpToVector[(err[loc[i]] - q + FMaxRSLength) % FMaxRSLength];
                // recd[i] must be in polynomial form
                recd[loc[i]] = (short)(recd[loc[i]] ^ err[loc[i]]);
              }
            }
          }
          else {
            // no. roots != degree of elp => >tt errors and cannot solve
            result = -1;
            // Signal an error.
            for (i = 0; i <= (FRSLength - 1); i++) {
              // could return error flag if desired
              if (recd[i] != -1) {
                // convert recd[] to polynomial form
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
              // just output received codeword as is
            }
          }
        }
        else {
          // if l[u] <= tt then
          // elp has degree has degree >tt hence cannot solve
          for (i = 0; i <= (FRSLength - 1); i++) {
            // could return error flag if desired
            if (recd[i] != -1) {
              // convert recd[] to polynomial form
              recd[i] = ExpToVector[recd[i]];
            }
            else {
              recd[i] = 0;
            }
            // just output received codeword as is
          }
        }
      }
      else {
        // If syn_error <> 0 then
        // no non-zero syndromes => no errors: output received codeword
        for (i = 0; i <= (FRSLength - 1); i++) {
          if (recd[i] != -1) {
            // convert recd[] to polynomial form
            recd[i] = ExpToVector[recd[i]];
          }
          else {
            recd[i] = 0;
          }
          result = 0;
          // No errors ocurred.
        }
      }

      //xDecoded = new byte[FRSLength - 1];
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        xDecoded[nI] = (byte)recd[nI];
      }
      return result;
    }

    public int DecodeRSEx(ref byte[] xData, ref byte[] xParity, ref byte[] xDecoded)
    {
      int result;
      string cStr;
      int nI;
      int nJ;
      int nK;
      int i;
      int j;
      short u;
      short q;
      short[][] elp;        // Array[0..np+1 , 0..np - 1] of smallint ;
      short[] d;            // Array[0..np+1] of smallint ;
      short[] l;            // Array[0..np+1] of smallint ;
      short[] u_lu;         // Array[0..np+1] of smallint ;
      short[] s;            // Array[0..np]   of smallint ;
      short count;
      short syn_error;
      int lpc;
      short[] root;         // Array[0..MaxErrors - 1] of smallint ;
      short[] loc;          // Array[0..MaxErrors - 1] of smallint ;
      short[] z;            // Array[0..MaxErrors]     of smallint ;
      short[] err;          // Array[0..nn-1]          of smallint ;
      short[] reg;          // Array[0..MaxErrors]     of smallint ;

      // DecodeRS
      elp = new short[FParityLength + 1 + 1][];
      for (lpc = 0; lpc < elp.Length; lpc++) {
        elp[lpc] = new short[FParityLength - 1 + 1];
        //@ Unsupported function or procedure: 'SetLength'
        //elp[lpc].Length = FParityLength - 1 + 1;
      }
      d = new short[FParityLength + 1 + 1];
      l = new short[FParityLength + 1 + 1];
      u_lu = new short[FParityLength + 1 + 1];
      s = new short[FParityLength + 1];
      root = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      loc = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      z = new short[Convert.ToInt64(FParityLength / 2) + 1];
      err = new short[FRSLength - 1 + 1];
      reg = new short[Convert.ToInt64(FParityLength / 2) + 1];
      for (nI = 0; nI <= (FParityLength - 1); nI++) {
        recd[nI] = xParity[nI];
      }
      //for (nI = 0; nI <= (FRSLength - 1); nI++) {
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        recd[FParityLength + nI] = xData[nI];
      }
      for (i = 0; i <= (FRSLength - 1); i++) {
        recd[i] = VectorToExp[recd[i]];
      }
      // put recd[i] into index form
      count = 0;
      syn_error = 0;
      result = 0;
      // first form the syndromes
      for (i = 1; i <= FParityLength; i++) {
        s[i] = 0;
        for (j = 0; j <= (FRSLength - 1); j++) {
          if (recd[j] != -1) {
            // recd[j] in index form
            s[i] = (short)(s[i] ^ ExpToVector[(recd[j] + i * j) % FMaxRSLength]);
          }
        }
        // convert syndrome from polynomial form to index form
        if ((s[i] != 0)) {
          syn_error = 1;
          // set flag if non-zero syndrome => error
        }
        s[i] = VectorToExp[s[i]];
      }
      if (syn_error != 0) {
        // if errors, try and correct
        // Compute the error location polynomial via the Berlekamp
        // iterative algorithm, following the terminology of Lin and
        // Costello :   d[u] is the 'mu'th discrepancy, where u='mu'+1
        // and 'mu' (the Greek letter!) is the step number ranging from
        // -1 to 2*tt (see L&C),  l[u] is the degree of the elp at that
        // step, and u_l[u] is the difference between the step number
        // and the degree of the elp.
        // Initialize table entries
        d[0] = 0;
        // index form
        d[1] = s[1];
        // index form
        elp[0][0] = 0;
        // index form
        elp[1][0] = 1;
        // polynomial form
        for (i = 1; i <= (FParityLength - 1); i++) {
          elp[0][i] = -1;
          // index form
          elp[1][i] = 0;
          // polynomial form
        }
        l[0] = 0;
        l[1] = 0;
        u_lu[0] = -1;
        u_lu[1] = 0;
        u = 0;
        while (((u < FParityLength) && (l[u + 1] <= Convert.ToInt64(FParityLength / 2)))) {
          u++;
          if ((d[u] == -1)) {
            l[u + 1] = l[u];
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = elp[u][i];
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          else {
            // search for words with greatest u_lu[q] for which d[q]!=0
            q = (short)(u - 1);
            while (((d[q] == -1) && (q > 0))) {
              q -= 1;
            }
            // have found first non-zero d[q]
            if ((q > 0)) {
              j = q;
              while (j > 0) {
                j -= 1;
                if (((d[j] != -1) && (u_lu[q] < u_lu[j]))) {
                  q = (short)j;
                }
              }
            }
            // have now found q such that d[u]!=0 and u_lu[q] is maximum
            // store degree of new elp polynomial
            if ((l[u] > l[q] + u - q)) {
              l[u + 1] = l[u];
            }
            else {
              l[u + 1] = (short)(l[q] + u - q);
            }
            // form new elp(x)
            for (i = 0; i <= (FParityLength - 1); i++) {
              elp[u + 1][i] = 0;
            }
            for (i = 0; i <= l[q]; i++) {
              // if (elp[q][i] <> -1) then elp[u+1][i+u-q] := ExpToVector[(d[u] + FRSLength - d[q] + elp[q][i]) mod FMaxRSLength] ;
              if ((elp[q][i] != -1)) {
                elp[u + 1][i + u - q] = ExpToVector[(d[u] + FMaxRSLength - d[q] + elp[q][i]) % FMaxRSLength];
              }
            }
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = (short)(elp[u + 1][i] ^ elp[u][i]);
              // convert old elp value to index
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          u_lu[u + 1] = (short)(u - l[u + 1]);
          // form (u+1)th discrepancy
          if (u < FParityLength) {
            // no discrepancy computed on last iteration
            if ((s[u + 1] != -1)) {
              d[u + 1] = ExpToVector[s[u + 1]];
            }
            else {
              d[u + 1] = 0;
            }
            for (i = 1; i <= l[u + 1]; i++) {
              if (((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0))) {
                d[u + 1] = (short)(d[u + 1] ^ ExpToVector[(s[u + 1 - i] + VectorToExp[elp[u + 1][i]]) % FMaxRSLength]);
              }
            }
            // put d[u+1] into index form
            d[u + 1] = VectorToExp[d[u + 1]];
          }
        }
        // end While
        u++;
        if (l[u] <= Convert.ToInt64(FParityLength / 2)) {
          // can correct error
          // put elp into index form
          for (i = 0; i <= l[u]; i++) {
            elp[u][i] = VectorToExp[elp[u][i]];
          }
          // find roots of the error location polynomial
          for (i = 1; i <= l[u]; i++) {
            reg[i] = elp[u][i];
          }
          // for i := 1 to FRSLength do begin
          for (i = 1; i <= FMaxRSLength; i++) {
            q = 1;
            for (j = 1; j <= l[u]; j++) {
              if (reg[j] != -1) {
                reg[j] = (short)((reg[j] + j) % FMaxRSLength);
                q = (short)(q ^ ExpToVector[reg[j]]);
              }
            }
            if (q == 0) {
              // store root and error location number indices
              root[count] = (short)i;
              // loc[count] := FRSLength - i ;
              loc[count] = (short)(FMaxRSLength - i);
              count++;
            }
          }
          if (count == l[u]) {
            // no. roots = degree of elp hence <= tt errors
            result = count;
            // form polynomial z(x)
            for (i = 1; i <= l[u]; i++) {
              // Z[0] = 1 always - do not need
              if (((s[i] != -1) && (elp[u][i] != -1))) {
                z[i] = (short)(ExpToVector[s[i]] ^ ExpToVector[elp[u][i]]);
              }
              else if (((s[i] != -1) && (elp[u][i] == -1))) {
                z[i] = ExpToVector[s[i]];
              }
              else if (((s[i] == -1) && (elp[u][i] != -1))) {
                z[i] = ExpToVector[elp[u][i]];
              }
              else {
                z[i] = 0;
              }
              for (j = 1; j <= (i - 1); j++) {
                if (((s[j] != -1) && (elp[u][i - j] != -1))) {
                  z[i] = (short)(z[i] ^ ExpToVector[(elp[u][i - j] + s[j]) % FMaxRSLength]);
                }
              }
              // put into index form
              z[i] = VectorToExp[z[i]];
            }
            // evaluate errors at locations given by
            // error location numbers loc[i]
            for (i = 0; i <= (FRSLength - 1); i++) {
              // for i := 0 to (FMaxRSLength - 1) do begin
              err[i] = 0;
              // convert recd[] to polynomial form
              if (recd[i] != -1) {
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
            }
            for (i = 0; i <= (l[u] - 1); i++) {
              // compute numerator of error term first
              err[loc[i]] = 1;
              // accounts for z[0]
              for (j = 1; j <= l[u]; j++) {
                if (z[j] != -1) {
                  err[loc[i]] = (short)(err[loc[i]] ^ ExpToVector[(z[j] + j * root[i]) % FMaxRSLength]);
                }
              }
              if (err[loc[i]] != 0) {
                err[loc[i]] = VectorToExp[err[loc[i]]];
                q = 0;
                // form denominator of error term
                for (j = 0; j <= (l[u] - 1); j++) {
                  if (j != i) {
                    q = (short)(q + VectorToExp[1 ^ ExpToVector[(loc[j] + root[i]) % FMaxRSLength]]);
                  }
                }
                q = (short)(q % FMaxRSLength);
                // err[loc[i]] := ExpToVector[(err[loc[i]] - q + FRSLength) mod FMaxRSLength] ;
                err[loc[i]] = ExpToVector[(err[loc[i]] - q + FMaxRSLength) % FMaxRSLength];
                // recd[i] must be in polynomial form
                recd[loc[i]] = (short)(recd[loc[i]] ^ err[loc[i]]);
              }
            }
          }
          else {
            // no. roots != degree of elp => >tt errors and cannot solve
            result = -1;
            // Signal an error.
            for (i = 0; i <= (FRSLength - 1); i++) {
              // could return error flag if desired
              if (recd[i] != -1) {
                // convert recd[] to polynomial form
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
              // just output received codeword as is
            }
          }
        }
        else {
          // if l[u] <= tt then
          // elp has degree has degree >tt hence cannot solve
          for (i = 0; i <= (FRSLength - 1); i++) {
            // could return error flag if desired
            if (recd[i] != -1) {
              // convert recd[] to polynomial form
              recd[i] = ExpToVector[recd[i]];
            }
            else {
              recd[i] = 0;
            }
            // just output received codeword as is
          }
        }
      }
      else {
        // If syn_error <> 0 then
        // no non-zero syndromes => no errors: output received codeword
        for (i = 0; i <= (FRSLength - 1); i++) {
          if (recd[i] != -1) {
            // convert recd[] to polynomial form
            recd[i] = ExpToVector[recd[i]];
          }
          else {
            recd[i] = 0;
          }
          result = 0;
          // No errors ocurred.
        }
      }

      // for nI := FParityLength to (FRSLength - 1) do xDecoded[nI-FParityLength] := Recd[nI] ;
      for (nI = FParityLength; nI <= (FRSLength - 1); nI++) {
        xDecoded[nI - FParityLength] = (byte)recd[nI];
      }
      return result;
    }

    public void SetGFDimension(int value)
    {
      FGFDimension = value;
      //ガロア体の次元が変わったらすべて作成しなおす必要がある
      ReInitParameters(FGFDimension, FParityLength, FRSLength);
    }

  }
}

別実装のコードです。iPentecGalois.cs と iPentecReedSolomonCodec.cs のコードで動作します。
iPentecGalois.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iPentec.ReedSolomonCodec
{
  public class iPentecGalois
  {
        private byte[] PP;
        // specify irreducible polynomial coeffts
        // ガロア体原始多項式
        private byte[][] pPP = new byte[16+1][];
        private int FTableLength = 0;
        public int[] gexp;
        public int[] glog;


        // ガロア体原始多項式
        public static byte[] PP2 = { 1, 1, 1 };
        public static byte[] PP3 = { 1, 1, 0, 1 };        // 1 + x + x^3
        public static byte[] PP4 = { 1, 1, 0, 0, 1 };        // 1 + x + x^4
        public static byte[] PP5 = { 1, 0, 1, 0, 0, 1 };        // 1 + x^2 + x^5
        public static byte[] PP6 = { 1, 1, 0, 0, 0, 0, 1 };        // 1 + x + x^6
        public static byte[] PP7 = { 1, 0, 0, 1, 0, 0, 0, 1 };        // 1 + x^3 + x^7
        public static byte[] PP8 = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };        // 1+x^2+x^3+x^4+x^8
        public static byte[] PP9 = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };        // 1+x^4+x^9
        public static byte[] PP10 = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^3+x^10
        public static byte[] PP11 = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^2+x^11
        public static byte[] PP12 = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };        // 1+x+x^4+x^6+x^12
        public static byte[] PP13 = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^3+x^4+x^13
        public static byte[] PP14 = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };        // 1+x+x^6+x^10+x^14
        public static byte[] PP15 = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^15
        public static byte[] PP16 = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };    

        // gexp: array [0..512] of integer;
        // glog: array [0..512] of integer;
        // 1+x+x^3+x^12+x^16
        //Constructor  Create()
        //public iPentecGalois : base()

        public iPentecGalois()
        {
          pPP[2] = PP2;
          pPP[3] = PP3;
          pPP[4] = PP4;
          pPP[5] = PP5;
          pPP[6] = PP6;
          pPP[7] = PP7;
          pPP[8] = PP8;
          pPP[9] = PP9;
          pPP[10] = PP10;
          pPP[11] = PP11;
          pPP[12] = PP12;
          pPP[13] = PP13;
          pPP[14] = PP14;
          pPP[15] = PP15;
          pPP[16] = PP16;  
        }

        public void InitTables(int Dimension)
        {
          // * initialize the table of powers of alpha */
          // init_exp_table();
          init_exp_table(Dimension);
        }

        private void init_exp_table(int Dimension)
        {
          int i;
          short mask;
          FTableLength = (1 << Dimension);
          gexp = new int[FTableLength];
          glog = new int[FTableLength];
          SetPrimitive(ref PP, Dimension);
          mask = 1;
          gexp[Dimension] = 0;
          for (i = 0; i <= (Dimension - 1); i++) {
            gexp[i] = mask;
            glog[gexp[i]] = i;
            if (PP[i] != 0) {
              gexp[Dimension] = gexp[Dimension] ^ mask;
            }
            mask = (short)(mask << 1);
          }
          glog[gexp[Dimension]] = Dimension;
          mask = (short)(mask >> 1);
          for (i = (Dimension + 1); i <= (FTableLength - 1); i++) {
            if (gexp[i - 1] >= mask) {
              gexp[i] = gexp[Dimension] ^ ((gexp[i - 1] ^ mask) << 1);
            }
            else {
              gexp[i] = gexp[i - 1] << 1;
            }
            glog[gexp[i]] = i;
          }
        }

        private void SetPrimitive(ref byte[] PP, int nIdx)
        {
          Array.Copy(PP, nIdx, PP, 0, (nIdx + 1));
          //@ Unsupported function or procedure: 'Move'
          //Move(PP[nIdx], PP, (nIdx + 1));
        }

        // /* multiplication using logarithms */
        public int gmult(int a, int b)
        {
          int result;
          int i;
          int j;
          if ((a == 0) || (b == 0)) {
            result = 0;
          }
          else {
            i = glog[a];
            j = glog[b];
            // result:=gexp[i+j];                  //テーブルの長さが2倍のとき
            result = gexp[(i + j) % (FTableLength - 1)];
            // テーブルの長さがぴったりのとき
          }
          return result;
        }

        public int ginv(int elt)
        {
          int result;
          result = gexp[255 - glog[elt]];
          return result;
        }
  }
}
iPentecReedSolomonCodec.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iPentec.ReedSolomonCodec
{
  public class iPentecReedSolomonCodec
  {
    private int NPAR = 0;
    private int MAXDEG = 0;
    private int FDimension = 0;
    private iPentecGalois GT = null;
    private int FNErasures = 0;
    private int[] ErasureLocs;
    private int[] ErrorLocs;
    private int NErrors = 0;
    private int[] Lambda;
    // [MAXDEG];
    private int[] Omega;
    public int[] pBytes;
    public int[] synBytes;
    public int[] genPoly;

    public int Dimension
    {
      get
      {
        return FDimension;
      }
      set
      {
        // [MAXDEG];
        if (FDimension != value) {
          FDimension = value;
        }
      }
    }

    //public TiPentecReedSolomonCodec(Component Aowner) : base(Aowner)
    public iPentecReedSolomonCodec()
    {
      FDimension = 8;
      GT = new iPentecGalois();
    }

    /*
    protected override void Dispose()
    {

    }
    */

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  初期化
    public void initialize_ecc(int ParityLength)
    {
      NPAR = ParityLength;
      MAXDEG = NPAR * 2;
      // * Initialize the galois field arithmetic tables */
      GT.InitTables(FDimension);
      // init_galois_tables();
      // * Compute the encoder generator polynomial */
      genPoly = new int[MAXDEG * 2];
      compute_genpoly(NPAR, out genPoly);
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Decode
    //デコード関数
    //デコード関数を呼び出したのち check_syndrome でシンドロームを求める
    public void decode_data(ref char[] data, int nbytes)
    {
      int i;
      int j;
      int sum;
      synBytes = new int[MAXDEG];
      for (j = 0; j < NPAR; j++) {
        // for j:=0 to 8-1 do begin
        sum = 0;
        for (i = 0; i < nbytes; i++) {
          sum = ((byte)data[i]) ^ GT.gmult(GT.gexp[j + 1], sum);
        }
        synBytes[j] = sum;
      }
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Check Syndrome
    //    シンドローム算出
    //    Decodeを事前に呼び出す必要がある
    public int check_syndrome()
    {
      int result;
      int i;
      int nz;
      nz = 0;
      for (i = 0; i < NPAR; i++) {
        if (synBytes[i] != 0) {
          nz = 1;
        }
      }
      result = nz;
      return result;
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Encode
    //    エンコード関数 コードワード版
    public void encode_data(char[] msg, int nbytes, out char[] dst)
    {
      int i;
      int dbyte;
      int j;
      int[] LFSR;
      LFSR = new int[NPAR + 1];
      for (i = 0; i <= NPAR; i++) {
        LFSR[i] = 0;
      }
      for (i = 0; i < nbytes; i++) {
        dbyte = ((byte)msg[i]) ^ LFSR[NPAR - 1];
        for (j = NPAR - 1; j >= 1; j--) {
          LFSR[j] = LFSR[j - 1] ^ GT.gmult(genPoly[j], dbyte);
        }
        LFSR[0] = GT.gmult(genPoly[0], dbyte);
      }
      pBytes = new int[NPAR];
      for (i = 0; i < NPAR; i++) {
        pBytes[i] = LFSR[i];
      }
      build_codeword(msg, nbytes, out dst);
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Encode Parity
    //    エンコード関数 パリティ分離版
    public void encode_data_parity(char[] msg, int nbytes, out char[] Parity)
    {
      int i;
      int dbyte;
      int j;
      int[] LFSR;
      LFSR = new int[NPAR + 1];
      for (i = 0; i <= NPAR; i++) {
        LFSR[i] = 0;
      }
      for (i = 0; i < nbytes; i++) {
        dbyte = ((byte)msg[i]) ^ LFSR[NPAR - 1];
        for (j = NPAR - 1; j >= 1; j--) {
          LFSR[j] = LFSR[j - 1] ^ GT.gmult(genPoly[j], dbyte);
        }
        LFSR[0] = GT.gmult(genPoly[0], dbyte);
      }

      Parity = new char[NPAR];
      pBytes = new int[NPAR];
      for (i = 0; i < NPAR; i++) {
        Parity[i] = ((char)LFSR[i]);
      }
      // for i := 0 to NPAR-1 do Pareity := pBytes[i];

    }

    public short crc_ccitt(string msg, int leng)
    {
      short result = 0;
      return result;
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  correct errors erasures
    //    誤り訂正処理
    public int correct_errors_erasures(ref char[] codeword, int csize, int nerasures, int[] erasures)
    {
      int result;
      int r;
      int i;
      int j;
      byte err;
      int num;
      int denom;
      FNErasures = nerasures;
      for (i = 0; i < nerasures; i++) {
        ErasureLocs[i] = erasures[i];
      }
      Modified_Berlekamp_Massey();
      Find_Roots();
      if ((NErrors <= NPAR) && (NErrors > 0)) {
        // /* first check for illegal error locs */
        for (r = 0; r < NErrors; r++) {
          if (ErrorLocs[r] >= csize) {
            result = 0;
            return result;
          }
        }
        for (r = 0; r < NErrors; r++) {
          i = ErrorLocs[r];
          // /* evaluate Omega at alpha^(-i) */
          num = 0;
          for (j = 0; j < MAXDEG; j++) {
            num = num ^ GT.gmult(Omega[j], GT.gexp[((255 - i) * j) % 255]);
          }
          // /* evaluate Lambda' (derivative) at alpha^(-i) ; all odd powers disappear */
          denom = 0;
          j = 1;
          while ((j < MAXDEG)) {
            denom = denom ^ GT.gmult(Lambda[j], GT.gexp[((255 - i) * (j - 1)) % 255]);
            j += 2;
          }
          err = (byte)GT.gmult(num, GT.ginv(denom));
          //codeword[csize - i - 1] = ((char)((byte)codeword[csize - i - 1]) ^ err);
          byte b = (byte)codeword[csize - i - 1];
          b = (byte)(b ^ err);
          codeword[csize - i - 1] = (char)b;
        }
        result = 1;
        return result;
      }
      else {
        result = 0;
      }
      return result;
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Compute GenPoly
    //    誤り訂正関数作成
    //    誤り訂正関数はエンコード時のみ使用される
    protected void compute_genpoly(int nbytes, out int[] genpoly)
    {
      genpoly = new int[0];

      int i;
      int[] tp = new int[255 + 1];
      int[] tp1 = new int[255 + 1];
      // /* multiply (x + a^n) for n = 1 to nbytes */
      zero_poly(out tp1);
      tp1[0] = 1;
      for (i = 1; i <= nbytes; i++) {
        zero_poly(out tp);
        tp[0] = GT.gexp[i];
        // * set up x+a^n */
        tp[1] = 1;
        mult_polys(out genpoly, tp, tp1);
        copy_poly(out tp1, genpoly);
      }
      // QRコード用 誤り訂正多項式
      // for i := 0 to nbytes do begin
      // genpoly[i]:=GT.gexp[GT.glog[genpoly[i]] - (nbytes-i)];
      // end;

    }

    protected void build_codeword(char[] msg, int nbytes, out char[] dst)
    {
      int i;
      dst = new char[nbytes];
      for (i = 0; i < nbytes; i++) {
        dst[i] = msg[i];
      }
      for (i = 0; i < NPAR; i++) {
        dst[i + nbytes] = ((char)pBytes[NPAR - 1 - i]);
      }
    }

    protected void Modified_Berlekamp_Massey()
    {
      int n;
      int l;
      int l2;
      int k;
      int d;
      int i;
      int[] psi;
      int[] psi2;
      int[] DA;
      int[] gamma;
      psi = new int[MAXDEG];
      psi2 = new int[MAXDEG];
      DA = new int[MAXDEG];
      gamma = new int[MAXDEG];
      // /* initialize Gamma, the erasure locator polynomial */
      init_gamma(out gamma);
      // /* initialize to z */
      copy_poly(out DA, gamma);
      mul_z_poly(ref DA);
      copy_poly(out psi, gamma);
      k = -1;
      l = FNErasures;
      for (n = FNErasures; n < NPAR; n++) {
        // for n:=FNErasures to 8-1 do begin
        d = compute_discrepancy(psi, synBytes, l, n);
        if (d != 0) {
          // /* psi2 = psi - d*D */
          for (i = 0; i < MAXDEG; i++) {
            psi2[i] = psi[i] ^ GT.gmult(d, DA[i]);
          }
          if (l < (n - k)) {
            l2 = n - k;
            k = n - l;
            // /* D = scale_poly(ginv(d), psi); */
            for (i = 0; i < MAXDEG; i++) {
              DA[i] = GT.gmult(psi[i], GT.ginv(d));
            }
            l = l2;
          }
          // /* psi = psi2 */
          for (i = 0; i < MAXDEG; i++) {
            psi[i] = psi2[i];
          }
        }
        mul_z_poly(ref DA);
      }
      // λの初期化
      Lambda = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        Lambda[i] = psi[i];
      }
      compute_modified_omega();
    }

    // * gamma = product (1-z*a^Ij) for erasure locs Ij */
    protected void init_gamma(out int[] gamma)
    {
      int e;
      int[] tmp;
      tmp = new int[MAXDEG];
      zero_poly(out gamma);
      zero_poly(out tmp);
      gamma[0] = 1;
      for (e = 0; e < FNErasures; e++) {
        copy_poly(out tmp, gamma);
        scale_poly(GT.gexp[ErasureLocs[e]], out tmp);
        mul_z_poly(ref tmp);
        add_polys(out gamma, tmp);
      }
    }

    protected int compute_discrepancy(int[] lambda, int[] S, int L, int n)
    {
      int result;
      int i;
      int sum;
      sum = 0;
      for (i = 0; i <= L; i++) {
        sum = sum ^ GT.gmult(lambda[i], S[n - i]);
      }
      result = sum;
      return result;
    }

    protected void compute_modified_omega()
    {
      int i;
      int[] product;
      product = new int[MAXDEG * 2];
      mult_polys(out product, Lambda, synBytes);
      // ωの初期化 (0でクリア後 productで初期値を代入)
      Omega = new int[MAXDEG];
      zero_poly(out Omega);
      for (i = 0; i < NPAR; i++) {
        Omega[i] = product[i];
      }
      //this.Finalize(product);
    }

    protected void Find_Roots()
    {
      int sum;
      int r;
      int k;
      NErrors = 0;
      for (r = 1; r < 256; r++) {
        sum = 0;
        // /* evaluate lambda at r */
        for (k = 0; k < NPAR + 1; k++) {
          sum = sum ^ GT.gmult(GT.gexp[(k * r) % 255], Lambda[k]);
        }
        if ((sum == 0)) {
          ErrorLocs[NErrors] = 255 - r;
          NErrors++;
        }
      }
    }

    public void zero_poly(out int[] poly)
    {
      int i;
      poly = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        poly[i] = 0;
      }
    }

    public void copy_poly(out int[] dst, int[] src)
    {
      int i;
      dst = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        dst[i] = src[i];
      }
    }

    public void add_polys(out int[] dst, int[] src)
    {
      int i;
      dst = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        dst[i] = dst[i] ^ src[i];
      }
    }

    // /* multiply by z, i.e., shift right by 1 */
    protected void mul_z_poly(ref int[] src)
    {
      int i;
      src = new int[MAXDEG - 1];
      for (i = MAXDEG - 1; i >= 1; i--) {
        src[i] = src[i - 1];
      }
      src[0] = 0;
    }

    public void scale_poly(int k, out int[] poly)
    {
      int i;
      poly = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        poly[i] = GT.gmult(k, poly[i]);
      }
    }

    public void mult_polys(out int[] dst, int[] p1, int[] p2)
    {
      int i;
      int j;
      int[] tmp1;
      tmp1 = new int[MAXDEG * 2];

      dst = new int[MAXDEG * 2];
      for (i = 0; i < (MAXDEG * 2); i++) {
        dst[i] = 0;
      }

      for (i = 0; i < MAXDEG; i++) {
        for (j = MAXDEG; j < (MAXDEG * 2); j++) {
          tmp1[j] = 0;
        }
        // /* scale tmp1 by p1[i] */
        for (j = 0; j < MAXDEG; j++) {
          tmp1[j] = GT.gmult(p2[j], p1[i]);
        }
        // /* and mult (shift) tmp1 right by i */
        j = (MAXDEG * 2) - 1;
        while ((j >= i)) {
          tmp1[j] = tmp1[j - i];
          j -= 1;
        }
        for (j = 0; j < i; j++) {
          tmp1[j] = 0;
        }
        // /* add into partial product */
        for (j = 0; j < (MAXDEG * 2); j++) {
          dst[j] = dst[j] ^ tmp1[j];
        }
      }
    }
  } // end TiPentecReedSolomonCodec
}

前のバージョンのコード

iPentecGalois.cs

ガロア体原始多項式実装クラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iPentec.ReedSolomonCodec
{
  public class iPentecGalois
  {
        private byte[] PP;
        // specify irreducible polynomial coeffts
        // ガロア体原始多項式
        private byte[][] pPP = new byte[16+1][];
        private int FTableLength = 0;
        public int[] gexp;
        public int[] glog;


        // ガロア体原始多項式
        public static byte[] PP2 = { 1, 1, 1 };
        public static byte[] PP3 = { 1, 1, 0, 1 };        // 1 + x + x^3
        public static byte[] PP4 = { 1, 1, 0, 0, 1 };        // 1 + x + x^4
        public static byte[] PP5 = { 1, 0, 1, 0, 0, 1 };        // 1 + x^2 + x^5
        public static byte[] PP6 = { 1, 1, 0, 0, 0, 0, 1 };        // 1 + x + x^6
        public static byte[] PP7 = { 1, 0, 0, 1, 0, 0, 0, 1 };        // 1 + x^3 + x^7
        public static byte[] PP8 = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };        // 1+x^2+x^3+x^4+x^8
        public static byte[] PP9 = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };        // 1+x^4+x^9
        public static byte[] PP10 = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^3+x^10
        public static byte[] PP11 = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^2+x^11
        public static byte[] PP12 = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };        // 1+x+x^4+x^6+x^12
        public static byte[] PP13 = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^3+x^4+x^13
        public static byte[] PP14 = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };        // 1+x+x^6+x^10+x^14
        public static byte[] PP15 = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^15
        public static byte[] PP16 = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };    

        public iPentecGalois()
        {
          pPP[2] = PP2;
          pPP[3] = PP3;
          pPP[4] = PP4;
          pPP[5] = PP5;
          pPP[6] = PP6;
          pPP[7] = PP7;
          pPP[8] = PP8;
          pPP[9] = PP9;
          pPP[10] = PP10;
          pPP[11] = PP11;
          pPP[12] = PP12;
          pPP[13] = PP13;
          pPP[14] = PP14;
          pPP[15] = PP15;
          pPP[16] = PP16;  
        }

        public void InitTables(int Dimension)
        {
          // * initialize the table of powers of alpha */
          // init_exp_table();
          init_exp_table(Dimension);
        }

        private void init_exp_table(int Dimension)
        {
          int i;
          short mask;
          FTableLength = (1 << Dimension);
          gexp = new int[FTableLength];
          glog = new int[FTableLength];
          SetPrimitive(ref PP, Dimension);
          mask = 1;
          gexp[Dimension] = 0;
          for (i = 0; i <= (Dimension - 1); i++) {
            gexp[i] = mask;
            glog[gexp[i]] = i;
            if (PP[i] != 0) {
              gexp[Dimension] = gexp[Dimension] ^ mask;
            }
            mask = (short)(mask << 1);
          }
          glog[gexp[Dimension]] = Dimension;
          mask = (short)(mask >> 1);
          for (i = (Dimension + 1); i <= (FTableLength - 1); i++) {
            if (gexp[i - 1] >= mask) {
              gexp[i] = gexp[Dimension] ^ ((gexp[i - 1] ^ mask) << 1);
            }
            else {
              gexp[i] = gexp[i - 1] << 1;
            }
            glog[gexp[i]] = i;
          }
        }

        private void SetPrimitive(ref byte[] PP, int nIdx)
        {
          Array.Copy(PP, nIdx, PP, 0, (nIdx + 1));
          //@ Unsupported function or procedure: 'Move'
          //Move(PP[nIdx], PP, (nIdx + 1));
        }

        // /* multiplication using logarithms */
        public int gmult(int a, int b)
        {
          int result;
          int i;
          int j;
          if ((a == 0) || (b == 0)) {
            result = 0;
          }
          else {
            i = glog[a];
            j = glog[b];
            // result:=gexp[i+j];                  //テーブルの長さが2倍のとき
            result = gexp[(i + j) % (FTableLength - 1)];
            // テーブルの長さがぴったりのとき
          }
          return result;
        }

        public int ginv(int elt)
        {
          int result;
          result = gexp[255 - glog[elt]];
          return result;
        }
  }
}

iPentecReedSolomon.cs

Reed Solomon符号化実装クラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iPentec.ReedSolomonCodec
{
  public class iPentecReedSolomon
  {
    //public static object[] pPP = new object[16 + 1];
    public static byte[][] pPP = new byte[16 + 1][];

    public const int DEFAULT_MM = 8;
    public const int DEFAULT_NP = 32;

    // ガロア体原始多項式
    public static byte[] PP2 = { 1, 1, 1 };
    public static byte[] PP3 = { 1, 1, 0, 1 };        // 1 + x + x^3
    public static byte[] PP4 = { 1, 1, 0, 0, 1 };        // 1 + x + x^4
    public static byte[] PP5 = { 1, 0, 1, 0, 0, 1 };        // 1 + x^2 + x^5
    public static byte[] PP6 = { 1, 1, 0, 0, 0, 0, 1 };        // 1 + x + x^6
    public static byte[] PP7 = { 1, 0, 0, 1, 0, 0, 0, 1 };        // 1 + x^3 + x^7
    public static byte[] PP8 = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };        // 1+x^2+x^3+x^4+x^8
    public static byte[] PP9 = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };        // 1+x^4+x^9
    public static byte[] PP10 = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^3+x^10
    public static byte[] PP11 = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x^2+x^11
    public static byte[] PP12 = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };        // 1+x+x^4+x^6+x^12
    public static byte[] PP13 = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^3+x^4+x^13
    public static byte[] PP14 = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };        // 1+x+x^6+x^10+x^14
    public static byte[] PP15 = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };        // 1+x+x^15
    public static byte[] PP16 = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };        // 1+x+x^3+x^12+x^16


    private int FGFDimension = 0;
    private int FRSLength = 0;
    private int FDataLength = 0;
    private int FParityLength = 0;
    private int FMaxRSLength = 0;
    private byte[] PP = new byte[16 + 1];

    // specify irreducible polynomial coeffts
    // ガロア体原始多項式
    private short[] ExpToVector;
    // alpha to
    private short[] VectorToExp;
    // index of
    private short[] gg;
    // 誤り訂正生成多項式
    private short[] bb;
    private short[] data;
    private short[] recd;
    private byte[] CodeWord;


    public int DataLength
    {
      get
      {
        return FDataLength;
      }
    }
  
    public iPentecReedSolomon()
    {
      pPP[2] = PP2;
      pPP[3] = PP3;
      pPP[4] = PP4;
      pPP[5] = PP5;
      pPP[6] = PP6;
      pPP[7] = PP7;
      pPP[8] = PP8;
      pPP[9] = PP9;
      pPP[10] = PP10;
      pPP[11] = PP11;
      pPP[12] = PP12;
      pPP[13] = PP13;
      pPP[14] = PP14;
      pPP[15] = PP15;
      pPP[16] = PP16;

      InitBuffers();
      // Clear the internal buffers
      // generate the Galois Field GF(2**mm)
      // Generate_gf(DEFAULT_MM);
      // FGFDimension:=DEFAULT_MM;
      InitParameters(DEFAULT_MM, DEFAULT_NP);
    }

    public iPentecReedSolomon(int GFDimension, int RSLength, int ParityLength)
    {
      pPP[2] = PP2;
      pPP[3] = PP3;
      pPP[4] = PP4;
      pPP[5] = PP5;
      pPP[6] = PP6;
      pPP[7] = PP7;
      pPP[8] = PP8;
      pPP[9] = PP9;
      pPP[10] = PP10;
      pPP[11] = PP11;
      pPP[12] = PP12;
      pPP[13] = PP13;
      pPP[14] = PP14;
      pPP[15] = PP15;
      pPP[16] = PP16;

      InitBuffers();
      InitParameters(DEFAULT_MM, DEFAULT_NP);

      SetGFDimension(GFDimension);
      SetRSLength(RSLength, ParityLength);

    }

    public void dispose()
    {
    }

    private void InitParameters(int GFDimension, int ParityLength)
    {
      FGFDimension = GFDimension;
      FParityLength = ParityLength;
      FMaxRSLength = (1 << FGFDimension) - 1; // nn=2**mm -1   Max length of codeword
      FRSLength = (1 << FGFDimension) - 1;    // nn=2**mm -1   Max length of codeword
      FDataLength = FRSLength - FParityLength;// data symbols, kk = nn-2*MaxErrors

      gg = new short[FParityLength + 1];
      bb = new short[FParityLength - 1 + 1];
      data = new short[FDataLength + 1];

      ExpToVector = new short[FRSLength + 1];
      VectorToExp = new short[FRSLength + 1];
      CodeWord = new byte[FRSLength - 1 + 1];
      recd = new short[FRSLength - 1 + 1];

      Generate_GF(FGFDimension);
      gen_poly();
    }

    private void ReInitParameters(int GFDimension, int ParityLength, int RSLength)
    {
      FGFDimension = GFDimension;
      FParityLength = ParityLength;
      FMaxRSLength = (1 << FGFDimension) - 1;        // nn=2**mm -1   Max length of codeword
      FRSLength = RSLength;
      FDataLength = FRSLength - FParityLength;       // data symbols, kk = nn-2*MaxErrors

      gg = new short[FParityLength + 1];
      bb = new short[FParityLength - 1 + 1];
      data = new short[FDataLength + 1];

      ExpToVector = new short[FMaxRSLength + 1];
      VectorToExp = new short[FMaxRSLength + 1];
      CodeWord = new byte[FRSLength - 1 + 1];
      recd = new short[FRSLength - 1 + 1];

      Generate_GF(FGFDimension);
      gen_poly();
    }

    protected void Generate_GF(int mm)
    {
      int i;
      short mask;
      SetPrimitive(ref PP, mm);
      mask = 1;
      ExpToVector[mm] = 0;
      for (i = 0; i <= (mm - 1); i++) {
        ExpToVector[i] = mask;
        VectorToExp[ExpToVector[i]] = (short)i;
        if (PP[i] != 0) {
          ExpToVector[mm] = (short)(ExpToVector[mm] ^ mask);
        }
        mask = (short)(mask << 1);
      }
      VectorToExp[ExpToVector[mm]] = (short)mm;
      mask = (short)(mask >> 1);
      for (i = (mm + 1); i <= (FRSLength - 1); i++) {
        if (ExpToVector[i - 1] >= mask) {
          ExpToVector[i] = (short)(ExpToVector[mm] ^ ((ExpToVector[i - 1] ^ mask) << 1));
        }
        else {
          ExpToVector[i] = (short)(ExpToVector[i - 1] << 1);
        }
        VectorToExp[ExpToVector[i]] = (short)i;
      }
      VectorToExp[0] = -1;
    }

    protected void gen_poly()
    {
      short i;
      short j;
      gg[0] = 2;
      // primitive element alpha = 2  for GF(2**mm)
      gg[1] = 1;
      // g(x) = (X+alpha) initially
      for (i = 2; i <= (FRSLength - FDataLength); i++) {
        gg[i] = 1;
        for (j = (short)(i - 1); j >= 1; j--) {
          if ((gg[j] != 0)) {
            gg[j] = (short)(gg[j - 1] ^ ExpToVector[(VectorToExp[gg[j]] + i) % FMaxRSLength]);
          }
          else {
            gg[j] = gg[j - 1];
          }
        }
        // gg[0] can never be zero
        gg[0] = ExpToVector[(VectorToExp[gg[0]] + i) % FMaxRSLength];
      }
      // Convert gg[] to index form for quicker encoding.
      for (i = 0; i <= FParityLength; i++) {
        gg[i] = VectorToExp[gg[i]];
      }
    }

    protected void SetPrimitive(ref byte[] PP, int nIdx)
    {
      //@ Unsupported function or procedure: 'Move'
      // Move(Units.iPentecReedSolomon.pPP[nIdx], PP, (nIdx + 1));
      //Array.Copy(pPP, nIdx, PP, 0, nIdx+1);
      //Array.Copy(pPP[nIdx], 0, PP, 0, nIdx+1);
      for (int i = 0; i < nIdx + 1; i++) {
        PP[i] = pPP[nIdx][i];
      }
    }

    // TReedSolomon.InitBuffers
    public void InitBuffers()
    {
      /*
        //@ Unsupported function or procedure: 'FillChar'
        FillChar(data, sizeof(data), 0);
        //@ Unsupported function or procedure: 'FillChar'
        FillChar(recd, sizeof(recd), 0);
        //@ Unsupported function or procedure: 'FillChar'
        FillChar(CodeWord, sizeof(CodeWord), 0);
       */
      if (data != null) {
        for (int i = 0; i < data.Length; i++) {
          data[i] = 0;
        }
      }
      if (recd != null) {
        for (int i = 0; i < recd.Length; i++) {
          recd[i] = 0;
        }
      }
      if (CodeWord != null) {
        for (int i = 0; i < CodeWord.Length; i++) {
          CodeWord[i] = 0;
        }
      }
    }

    public void EncodeRS(ref byte[] xData, ref byte[] xEncoded)
    {
      //int e;
      byte[] rswork = new byte[123 - 1 + 1];
      // RS符号計算用作業領域
      int nI;
      int i;
      int j;
      short feedback;
      //byte[] axData;

      for (i = 0; i < bb.Length; i++) {
        bb[i] = 0;
      }
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        //data[nI] = axData[nI];
        data[nI] = xData[nI];
      }
      for (i = (FDataLength - 1); i >= 0; i--) {
        feedback = VectorToExp[data[i] ^ bb[FParityLength - 1]];
        if ((feedback != -1)) {
          for (j = (FParityLength - 1); j >= 1; j--) {
            if ((gg[j] != -1)) {
              bb[j] = (short)(bb[j - 1] ^ ExpToVector[(gg[j] + feedback) % FMaxRSLength]);
            }
            else {
              bb[j] = bb[j - 1];
            }
          }
          bb[0] = ExpToVector[(gg[0] + feedback) % FMaxRSLength];
        }
        else {
          for (j = (FParityLength - 1); j >= 1; j--) {
            bb[j] = bb[j - 1];
          }
          bb[0] = 0;
        }
      }
      // put the transmitted codeword, made up of data
      // plus parity, in CodeWord
      for (nI = 0; nI <= (FParityLength - 1); nI++) {
        recd[nI] = bb[nI];
      }
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        recd[nI + FParityLength] = data[nI];
      }
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        CodeWord[nI] = (byte)recd[nI];
      }

      //@ Unsupported function or procedure: 'Move'
      //Move(CodeWord[0], xEncoded, FRSLength);
      Array.Copy(CodeWord, 0, xEncoded, 0, FRSLength);
    }

    public void EncodeRSEx(ref byte[] xData, ref byte[] xEncoded, ref byte[] xParity)
    {
      int nI;
      int i;
      int j;
      short feedback;
      int e;
      short[] invertgg;
      invertgg = new short[gg.Length];
      for (i = 0; i < gg.Length; i++) {
        //invertgg[i] = gg[gg.Length - 1 - 1 - i];
        invertgg[i] = gg[gg.Length - 1 - i];
      }
      for (i = 0; i < bb.Length; i++) {
        bb[i] = 0;
      }
      //for (nI = 0; nI <= (FRSLength - 1); nI++) {

      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        data[nI] = xData[nI];
      }
      for (i = (FDataLength - 1); i >= 0; i--) {
        feedback = VectorToExp[data[i] ^ bb[FParityLength - 1]];
        if ((feedback != -1)) {
          for (j = (FParityLength - 1); j >= 1; j--) {
            if ((gg[j] != -1)) {
              bb[j] = (short)(bb[j - 1] ^ ExpToVector[(gg[j] + feedback) % FMaxRSLength]);
            }
            else {
              bb[j] = bb[j - 1];
            }
          }
          bb[0] = ExpToVector[(gg[0] + feedback) % FMaxRSLength];
        }
        else {
          for (j = (FParityLength - 1); j >= 1; j--) {
            bb[j] = bb[j - 1];
          }
          bb[0] = 0;
        }
      }
      // put the transmitted codeword, made up of data
      // plus parity, in CodeWord
      for (nI = 0; nI <= (FParityLength - 1); nI++) {
        recd[nI] = bb[nI];
        xParity[nI] = (byte)bb[nI];
      }
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        recd[nI + FParityLength] = data[nI];
      }
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        CodeWord[nI] = (byte)recd[nI];
      }
      //@ Unsupported function or procedure: 'Move'
      //Move(CodeWord[0], xEncoded, FRSLength);
      Array.Copy(CodeWord, 0, xEncoded, 0, FRSLength);
    }

    //public int DecodeRS(ref object xData, ref object xDecoded)
    public int DecodeRS(ref byte[] xData, ref byte[] xDecoded)
    {
      int result;
      //byte[] axData;
      //byte[] axDecoded;
      //string cStr;
      int nI;
      int nJ;
      int nK;
      int i;
      int j;
      short u;
      short q;
      short[][] elp;            // Array[0..np+1 , 0..np - 1] of smallint ;
      short[] d;            // Array[0..np+1] of smallint ;
      short[] l;            // Array[0..np+1] of smallint ;
      short[] u_lu;            // Array[0..np+1] of smallint ;
      short[] s;            // Array[0..np]   of smallint ;
      short count;
      short syn_error;
      int lpc;
      short[] root;            // Array[0..MaxErrors - 1] of smallint ;
      short[] loc;            // Array[0..MaxErrors - 1] of smallint ;
      short[] z;            // Array[0..MaxErrors]     of smallint ;
      short[] err;            // Array[0..nn-1]          of smallint ;
      short[] reg;            // Array[0..MaxErrors]     of smallint ;
      // DecodeRS

      elp = new short[FParityLength + 1 + 1][];
      for (lpc = 0; lpc < elp.Length; lpc++) {
        //@ Unsupported function or procedure: 'SetLength'
        //elp[lpc].Length = FParityLength - 1 + 1;
        elp[lpc] = new short[FParityLength - 1 + 1];
      }

      d = new short[FParityLength + 1 + 1];
      l = new short[FParityLength + 1 + 1];
      u_lu = new short[FParityLength + 1 + 1];
      s = new short[FParityLength + 1];
      root = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      loc = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      z = new short[Convert.ToInt64(FParityLength / 2) + 1];
      err = new short[FRSLength - 1 + 1];
      reg = new short[Convert.ToInt64(FParityLength / 2) + 1];
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        //recd[nI] = axData[nI];
        recd[nI] = xData[nI];
      }
      for (i = 0; i <= (FRSLength - 1); i++) {
        recd[i] = VectorToExp[recd[i]];
      }
      // put recd[i] into index form
      count = 0;
      syn_error = 0;
      result = 0;
      // first form the syndromes
      for (i = 1; i <= FParityLength; i++) {
        s[i] = 0;
        for (j = 0; j <= (FRSLength - 1); j++) {
          if (recd[j] != -1) {
            // recd[j] in index form
            s[i] = (short)(s[i] ^ ExpToVector[(recd[j] + i * j) % FMaxRSLength]);
          }
        }
        // convert syndrome from polynomial form to index form
        if ((s[i] != 0)) {
          syn_error = 1;
          // set flag if non-zero syndrome => error
        }
        s[i] = VectorToExp[s[i]];
      }
      if (syn_error != 0) {
        d[0] = 0;
        // index form
        d[1] = s[1];
        // index form
        elp[0][0] = 0;
        // index form
        elp[1][0] = 1;
        // polynomial form
        for (i = 1; i <= (FParityLength - 1); i++) {
          elp[0][i] = -1;
          // index form
          elp[1][i] = 0;
          // polynomial form
        }
        l[0] = 0;
        l[1] = 0;
        u_lu[0] = -1;
        u_lu[1] = 0;
        u = 0;
        while (((u < FParityLength) && (l[u + 1] <= Convert.ToInt64(FParityLength / 2)))) {
          u++;
          if ((d[u] == -1)) {
            l[u + 1] = l[u];
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = elp[u][i];
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          else {
            // search for words with greatest u_lu[q] for which d[q]!=0
            q = (short)(u - 1);
            while (((d[q] == -1) && (q > 0))) {
              q -= 1;
            }
            // have found first non-zero d[q]
            if ((q > 0)) {
              j = q;
              while (j > 0) {
                j -= 1;
                if (((d[j] != -1) && (u_lu[q] < u_lu[j]))) {
                  q = (short)j;
                }
              }
            }
            // have now found q such that d[u]!=0 and u_lu[q] is maximum
            // store degree of new elp polynomial
            if ((l[u] > l[q] + u - q)) {
              l[u + 1] = l[u];
            }
            else {
              l[u + 1] = (short)(l[q] + u - q);
            }
            // form new elp(x)
            for (i = 0; i <= (FParityLength - 1); i++) {
              elp[u + 1][i] = 0;
            }
            for (i = 0; i <= l[q]; i++) {
              // if (elp[q][i] <> -1) then elp[u+1][i+u-q] := ExpToVector[(d[u] + FRSLength - d[q] + elp[q][i]) mod FMaxRSLength] ;
              if ((elp[q][i] != -1)) {
                elp[u + 1][i + u - q] = ExpToVector[(d[u] + FMaxRSLength - d[q] + elp[q][i]) % FMaxRSLength];
              }
            }
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = (short)(elp[u + 1][i] ^ elp[u][i]);
              // convert old elp value to index
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          u_lu[u + 1] = (short)(u - l[u + 1]);
          // form (u+1)th discrepancy
          if (u < FParityLength) {
            // no discrepancy computed on last iteration
            if ((s[u + 1] != -1)) {
              d[u + 1] = ExpToVector[s[u + 1]];
            }
            else {
              d[u + 1] = 0;
            }
            for (i = 1; i <= l[u + 1]; i++) {
              if (((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0))) {
                d[u + 1] = (short)(d[u + 1] ^ ExpToVector[(s[u + 1 - i] + VectorToExp[elp[u + 1][i]]) % FMaxRSLength]);
              }
            }
            // put d[u+1] into index form
            d[u + 1] = VectorToExp[d[u + 1]];
          }
        }
        // end While
        u++;
        if (l[u] <= Convert.ToInt64(FParityLength / 2)) {
          // can correct error
          // put elp into index form
          for (i = 0; i <= l[u]; i++) {
            elp[u][i] = VectorToExp[elp[u][i]];
          }
          // find roots of the error location polynomial
          for (i = 1; i <= l[u]; i++) {
            reg[i] = elp[u][i];
          }
          // for i := 1 to FRSLength do begin
          for (i = 1; i <= FMaxRSLength; i++) {
            q = 1;
            for (j = 1; j <= l[u]; j++) {
              if (reg[j] != -1) {
                reg[j] = (short)((reg[j] + j) % FMaxRSLength);
                q = (short)(q ^ ExpToVector[reg[j]]);
              }
            }
            if (q == 0) {
              // store root and error location number indices
              root[count] = (short)i;
              // loc[count] := FRSLength - i ;
              loc[count] = (short)(FMaxRSLength - i);
              count++;
            }
          }
          if (count == l[u]) {
            // no. roots = degree of elp hence <= tt errors
            result = count;
            // form polynomial z(x)
            for (i = 1; i <= l[u]; i++) {
              // Z[0] = 1 always - do not need
              if (((s[i] != -1) && (elp[u][i] != -1))) {
                z[i] = (short)(ExpToVector[s[i]] ^ ExpToVector[elp[u][i]]);
              }
              else if (((s[i] != -1) && (elp[u][i] == -1))) {
                z[i] = ExpToVector[s[i]];
              }
              else if (((s[i] == -1) && (elp[u][i] != -1))) {
                z[i] = ExpToVector[elp[u][i]];
              }
              else {
                z[i] = 0;
              }
              for (j = 1; j <= (i - 1); j++) {
                if (((s[j] != -1) && (elp[u][i - j] != -1))) {
                  z[i] = (short)(z[i] ^ ExpToVector[(elp[u][i - j] + s[j]) % FMaxRSLength]);
                }
              }
              // put into index form
              z[i] = VectorToExp[z[i]];
            }
            // evaluate errors at locations given by
            // error location numbers loc[i]
            for (i = 0; i <= (FRSLength - 1); i++) {
              // for i := 0 to (FMaxRSLength - 1) do begin
              err[i] = 0;
              // convert recd[] to polynomial form
              if (recd[i] != -1) {
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
            }
            for (i = 0; i <= (l[u] - 1); i++) {
              // compute numerator of error term first
              err[loc[i]] = 1;
              // accounts for z[0]
              for (j = 1; j <= l[u]; j++) {
                if (z[j] != -1) {
                  err[loc[i]] = (short)(err[loc[i]] ^ ExpToVector[(z[j] + j * root[i]) % FMaxRSLength]);
                }
              }
              if (err[loc[i]] != 0) {
                err[loc[i]] = VectorToExp[err[loc[i]]];
                q = 0;
                // form denominator of error term
                for (j = 0; j <= (l[u] - 1); j++) {
                  if (j != i) {
                    q = (short)(q + VectorToExp[1 ^ ExpToVector[(loc[j] + root[i]) % FMaxRSLength]]);
                  }
                }
                q = (short)(q % FMaxRSLength);
                // err[loc[i]] := ExpToVector[(err[loc[i]] - q + FRSLength) mod FMaxRSLength] ;
                err[loc[i]] = ExpToVector[(err[loc[i]] - q + FMaxRSLength) % FMaxRSLength];
                // recd[i] must be in polynomial form
                recd[loc[i]] = (short)(recd[loc[i]] ^ err[loc[i]]);
              }
            }
          }
          else {
            // no. roots != degree of elp => >tt errors and cannot solve
            result = -1;
            // Signal an error.
            for (i = 0; i <= (FRSLength - 1); i++) {
              // could return error flag if desired
              if (recd[i] != -1) {
                // convert recd[] to polynomial form
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
              // just output received codeword as is
            }
          }
        }
        else {
          // if l[u] <= tt then
          // elp has degree has degree >tt hence cannot solve
          for (i = 0; i <= (FRSLength - 1); i++) {
            // could return error flag if desired
            if (recd[i] != -1) {
              // convert recd[] to polynomial form
              recd[i] = ExpToVector[recd[i]];
            }
            else {
              recd[i] = 0;
            }
            // just output received codeword as is
          }
        }
      }
      else {
        // If syn_error <> 0 then
        // no non-zero syndromes => no errors: output received codeword
        for (i = 0; i <= (FRSLength - 1); i++) {
          if (recd[i] != -1) {
            // convert recd[] to polynomial form
            recd[i] = ExpToVector[recd[i]];
          }
          else {
            recd[i] = 0;
          }
          result = 0;
          // No errors ocurred.
        }
      }

      //xDecoded = new byte[FRSLength - 1];
      for (nI = 0; nI <= (FRSLength - 1); nI++) {
        xDecoded[nI] = (byte)recd[nI];
      }
      return result;
    }

    public int DecodeRSEx(ref byte[] xData, ref byte[] xParity, ref byte[] xDecoded)
    {
      int result;
      string cStr;
      int nI;
      int nJ;
      int nK;
      int i;
      int j;
      short u;
      short q;
      short[][] elp;        // Array[0..np+1 , 0..np - 1] of smallint ;
      short[] d;            // Array[0..np+1] of smallint ;
      short[] l;            // Array[0..np+1] of smallint ;
      short[] u_lu;         // Array[0..np+1] of smallint ;
      short[] s;            // Array[0..np]   of smallint ;
      short count;
      short syn_error;
      int lpc;
      short[] root;         // Array[0..MaxErrors - 1] of smallint ;
      short[] loc;          // Array[0..MaxErrors - 1] of smallint ;
      short[] z;            // Array[0..MaxErrors]     of smallint ;
      short[] err;          // Array[0..nn-1]          of smallint ;
      short[] reg;          // Array[0..MaxErrors]     of smallint ;

      // DecodeRS
      elp = new short[FParityLength + 1 + 1][];
      for (lpc = 0; lpc < elp.Length; lpc++) {
        elp[lpc] = new short[FParityLength - 1 + 1];
        //@ Unsupported function or procedure: 'SetLength'
        //elp[lpc].Length = FParityLength - 1 + 1;
      }
      d = new short[FParityLength + 1 + 1];
      l = new short[FParityLength + 1 + 1];
      u_lu = new short[FParityLength + 1 + 1];
      s = new short[FParityLength + 1];
      root = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      loc = new short[Convert.ToInt64(FParityLength / 2) - 1 + 1];
      z = new short[Convert.ToInt64(FParityLength / 2) + 1];
      err = new short[FRSLength - 1 + 1];
      reg = new short[Convert.ToInt64(FParityLength / 2) + 1];
      for (nI = 0; nI <= (FParityLength - 1); nI++) {
        recd[nI] = xParity[nI];
      }
      //for (nI = 0; nI <= (FRSLength - 1); nI++) {
      for (nI = 0; nI <= (FDataLength - 1); nI++) {
        recd[FParityLength + nI] = xData[nI];
      }
      for (i = 0; i <= (FRSLength - 1); i++) {
        recd[i] = VectorToExp[recd[i]];
      }
      // put recd[i] into index form
      count = 0;
      syn_error = 0;
      result = 0;
      // first form the syndromes
      for (i = 1; i <= FParityLength; i++) {
        s[i] = 0;
        for (j = 0; j <= (FRSLength - 1); j++) {
          if (recd[j] != -1) {
            // recd[j] in index form
            s[i] = (short)(s[i] ^ ExpToVector[(recd[j] + i * j) % FMaxRSLength]);
          }
        }
        // convert syndrome from polynomial form to index form
        if ((s[i] != 0)) {
          syn_error = 1;
          // set flag if non-zero syndrome => error
        }
        s[i] = VectorToExp[s[i]];
      }
      if (syn_error != 0) {
        // if errors, try and correct
        // Compute the error location polynomial via the Berlekamp
        // iterative algorithm, following the terminology of Lin and
        // Costello :   d[u] is the 'mu'th discrepancy, where u='mu'+1
        // and 'mu' (the Greek letter!) is the step number ranging from
        // -1 to 2*tt (see L&C),  l[u] is the degree of the elp at that
        // step, and u_l[u] is the difference between the step number
        // and the degree of the elp.
        // Initialize table entries
        d[0] = 0;
        // index form
        d[1] = s[1];
        // index form
        elp[0][0] = 0;
        // index form
        elp[1][0] = 1;
        // polynomial form
        for (i = 1; i <= (FParityLength - 1); i++) {
          elp[0][i] = -1;
          // index form
          elp[1][i] = 0;
          // polynomial form
        }
        l[0] = 0;
        l[1] = 0;
        u_lu[0] = -1;
        u_lu[1] = 0;
        u = 0;
        while (((u < FParityLength) && (l[u + 1] <= Convert.ToInt64(FParityLength / 2)))) {
          u++;
          if ((d[u] == -1)) {
            l[u + 1] = l[u];
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = elp[u][i];
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          else {
            // search for words with greatest u_lu[q] for which d[q]!=0
            q = (short)(u - 1);
            while (((d[q] == -1) && (q > 0))) {
              q -= 1;
            }
            // have found first non-zero d[q]
            if ((q > 0)) {
              j = q;
              while (j > 0) {
                j -= 1;
                if (((d[j] != -1) && (u_lu[q] < u_lu[j]))) {
                  q = (short)j;
                }
              }
            }
            // have now found q such that d[u]!=0 and u_lu[q] is maximum
            // store degree of new elp polynomial
            if ((l[u] > l[q] + u - q)) {
              l[u + 1] = l[u];
            }
            else {
              l[u + 1] = (short)(l[q] + u - q);
            }
            // form new elp(x)
            for (i = 0; i <= (FParityLength - 1); i++) {
              elp[u + 1][i] = 0;
            }
            for (i = 0; i <= l[q]; i++) {
              // if (elp[q][i] <> -1) then elp[u+1][i+u-q] := ExpToVector[(d[u] + FRSLength - d[q] + elp[q][i]) mod FMaxRSLength] ;
              if ((elp[q][i] != -1)) {
                elp[u + 1][i + u - q] = ExpToVector[(d[u] + FMaxRSLength - d[q] + elp[q][i]) % FMaxRSLength];
              }
            }
            for (i = 0; i <= l[u]; i++) {
              elp[u + 1][i] = (short)(elp[u + 1][i] ^ elp[u][i]);
              // convert old elp value to index
              elp[u][i] = VectorToExp[elp[u][i]];
            }
          }
          u_lu[u + 1] = (short)(u - l[u + 1]);
          // form (u+1)th discrepancy
          if (u < FParityLength) {
            // no discrepancy computed on last iteration
            if ((s[u + 1] != -1)) {
              d[u + 1] = ExpToVector[s[u + 1]];
            }
            else {
              d[u + 1] = 0;
            }
            for (i = 1; i <= l[u + 1]; i++) {
              if (((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0))) {
                d[u + 1] = (short)(d[u + 1] ^ ExpToVector[(s[u + 1 - i] + VectorToExp[elp[u + 1][i]]) % FMaxRSLength]);
              }
            }
            // put d[u+1] into index form
            d[u + 1] = VectorToExp[d[u + 1]];
          }
        }
        // end While
        u++;
        if (l[u] <= Convert.ToInt64(FParityLength / 2)) {
          // can correct error
          // put elp into index form
          for (i = 0; i <= l[u]; i++) {
            elp[u][i] = VectorToExp[elp[u][i]];
          }
          // find roots of the error location polynomial
          for (i = 1; i <= l[u]; i++) {
            reg[i] = elp[u][i];
          }
          // for i := 1 to FRSLength do begin
          for (i = 1; i <= FMaxRSLength; i++) {
            q = 1;
            for (j = 1; j <= l[u]; j++) {
              if (reg[j] != -1) {
                reg[j] = (short)((reg[j] + j) % FMaxRSLength);
                q = (short)(q ^ ExpToVector[reg[j]]);
              }
            }
            if (q == 0) {
              // store root and error location number indices
              root[count] = (short)i;
              // loc[count] := FRSLength - i ;
              loc[count] = (short)(FMaxRSLength - i);
              count++;
            }
          }
          if (count == l[u]) {
            // no. roots = degree of elp hence <= tt errors
            result = count;
            // form polynomial z(x)
            for (i = 1; i <= l[u]; i++) {
              // Z[0] = 1 always - do not need
              if (((s[i] != -1) && (elp[u][i] != -1))) {
                z[i] = (short)(ExpToVector[s[i]] ^ ExpToVector[elp[u][i]]);
              }
              else if (((s[i] != -1) && (elp[u][i] == -1))) {
                z[i] = ExpToVector[s[i]];
              }
              else if (((s[i] == -1) && (elp[u][i] != -1))) {
                z[i] = ExpToVector[elp[u][i]];
              }
              else {
                z[i] = 0;
              }
              for (j = 1; j <= (i - 1); j++) {
                if (((s[j] != -1) && (elp[u][i - j] != -1))) {
                  z[i] = (short)(z[i] ^ ExpToVector[(elp[u][i - j] + s[j]) % FMaxRSLength]);
                }
              }
              // put into index form
              z[i] = VectorToExp[z[i]];
            }
            // evaluate errors at locations given by
            // error location numbers loc[i]
            for (i = 0; i <= (FRSLength - 1); i++) {
              // for i := 0 to (FMaxRSLength - 1) do begin
              err[i] = 0;
              // convert recd[] to polynomial form
              if (recd[i] != -1) {
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
            }
            for (i = 0; i <= (l[u] - 1); i++) {
              // compute numerator of error term first
              err[loc[i]] = 1;
              // accounts for z[0]
              for (j = 1; j <= l[u]; j++) {
                if (z[j] != -1) {
                  err[loc[i]] = (short)(err[loc[i]] ^ ExpToVector[(z[j] + j * root[i]) % FMaxRSLength]);
                }
              }
              if (err[loc[i]] != 0) {
                err[loc[i]] = VectorToExp[err[loc[i]]];
                q = 0;
                // form denominator of error term
                for (j = 0; j <= (l[u] - 1); j++) {
                  if (j != i) {
                    q = (short)(q + VectorToExp[1 ^ ExpToVector[(loc[j] + root[i]) % FMaxRSLength]]);
                  }
                }
                q = (short)(q % FMaxRSLength);
                // err[loc[i]] := ExpToVector[(err[loc[i]] - q + FRSLength) mod FMaxRSLength] ;
                err[loc[i]] = ExpToVector[(err[loc[i]] - q + FMaxRSLength) % FMaxRSLength];
                // recd[i] must be in polynomial form
                recd[loc[i]] = (short)(recd[loc[i]] ^ err[loc[i]]);
              }
            }
          }
          else {
            // no. roots != degree of elp => >tt errors and cannot solve
            result = -1;
            // Signal an error.
            for (i = 0; i <= (FRSLength - 1); i++) {
              // could return error flag if desired
              if (recd[i] != -1) {
                // convert recd[] to polynomial form
                recd[i] = ExpToVector[recd[i]];
              }
              else {
                recd[i] = 0;
              }
              // just output received codeword as is
            }
          }
        }
        else {
          // if l[u] <= tt then
          // elp has degree has degree >tt hence cannot solve
          for (i = 0; i <= (FRSLength - 1); i++) {
            // could return error flag if desired
            if (recd[i] != -1) {
              // convert recd[] to polynomial form
              recd[i] = ExpToVector[recd[i]];
            }
            else {
              recd[i] = 0;
            }
            // just output received codeword as is
          }
        }
      }
      else {
        // If syn_error <> 0 then
        // no non-zero syndromes => no errors: output received codeword
        for (i = 0; i <= (FRSLength - 1); i++) {
          if (recd[i] != -1) {
            // convert recd[] to polynomial form
            recd[i] = ExpToVector[recd[i]];
          }
          else {
            recd[i] = 0;
          }
          result = 0;
          // No errors ocurred.
        }
      }

      // for nI := FParityLength to (FRSLength - 1) do xDecoded[nI-FParityLength] := Recd[nI] ;
      for (nI = FParityLength; nI <= (FRSLength - 1); nI++) {
        xDecoded[nI - FParityLength] = (byte)recd[nI];
      }
      return result;
    }

    public void SetGFDimension(int value)
    {
      FGFDimension = value;
      //ガロア体の次元が変わったらすべて作成しなおす必要がある
      ReInitParameters(FGFDimension, FParityLength, FRSLength);
    }

    public void SetRSLength(int RSLength, int ParityLength)
    {
      FRSLength = RSLength;
      FParityLength = ParityLength;
      FDataLength = FRSLength - FParityLength;  //data symbols, kk = nn-2*MaxErrors

      gg = new short[FParityLength + 1];
      bb = new short[FParityLength];
      data = new short[FDataLength + 1];
      CodeWord = new byte[FRSLength - 1 + 1];
      recd = new short[FRSLength - 1 + 1];

      gen_poly();
    }

    public void SetRSMaxLength()
    {
      int ml;
      ml = (1 << FGFDimension) - 1;
      // nn=2**mm -1   length of codeword
      //RSLength = ml;
      SetRSLength(ml, FParityLength);
    }
  }
} // end TiPentecReedSolomon

iPentecReedSolomonCodec.cs

Reed Solomon符号化実装クラス(別版)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iPentec.ReedSolomonCodec
{
  public class iPentecReedSolomonCodec
  {
    private int NPAR = 0;
    private int MAXDEG = 0;
    private int FDimension = 0;
    private iPentecGalois GT = null;
    private int FNErasures = 0;
    private int[] ErasureLocs;
    private int[] ErrorLocs;
    private int NErrors = 0;
    private int[] Lambda;
    // [MAXDEG];
    private int[] Omega;
    public int[] pBytes;
    public int[] synBytes;
    public int[] genPoly;

    public int Dimension
    {
      get
      {
        return FDimension;
      }
      set
      {
        // [MAXDEG];
        if (FDimension != value) {
          FDimension = value;
        }
      }
    }

    //public TiPentecReedSolomonCodec(Component Aowner) : base(Aowner)
    public iPentecReedSolomonCodec()
    {
      FDimension = 8;
      GT = new iPentecGalois();
    }

    /*
    protected override void Dispose()
    {

    }
    */

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  初期化
    public void initialize_ecc(int ParityLength)
    {
      NPAR = ParityLength;
      MAXDEG = NPAR * 2;
      // * Initialize the galois field arithmetic tables */
      GT.InitTables(FDimension);
      // init_galois_tables();
      // * Compute the encoder generator polynomial */
      genPoly = new int[MAXDEG * 2];
      compute_genpoly(NPAR, out genPoly);
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Decode
    //デコード関数
    //デコード関数を呼び出したのち check_syndrome でシンドロームを求める
    public void decode_data(ref char[] data, int nbytes)
    {
      int i;
      int j;
      int sum;
      synBytes = new int[MAXDEG];
      for (j = 0; j < NPAR; j++) {
        // for j:=0 to 8-1 do begin
        sum = 0;
        for (i = 0; i < nbytes; i++) {
          sum = ((byte)data[i]) ^ GT.gmult(GT.gexp[j + 1], sum);
        }
        synBytes[j] = sum;
      }
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Check Syndrome
    //    シンドローム算出
    //    Decodeを事前に呼び出す必要がある
    public int check_syndrome()
    {
      int result;
      int i;
      int nz;
      nz = 0;
      for (i = 0; i < NPAR; i++) {
        if (synBytes[i] != 0) {
          nz = 1;
        }
      }
      result = nz;
      return result;
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Encode
    //    エンコード関数 コードワード版
    public void encode_data(char[] msg, int nbytes, out char[] dst)
    {
      int i;
      int dbyte;
      int j;
      int[] LFSR;
      LFSR = new int[NPAR + 1];
      for (i = 0; i <= NPAR; i++) {
        LFSR[i] = 0;
      }
      for (i = 0; i < nbytes; i++) {
        dbyte = ((byte)msg[i]) ^ LFSR[NPAR - 1];
        for (j = NPAR - 1; j >= 1; j--) {
          LFSR[j] = LFSR[j - 1] ^ GT.gmult(genPoly[j], dbyte);
        }
        LFSR[0] = GT.gmult(genPoly[0], dbyte);
      }
      pBytes = new int[NPAR];
      for (i = 0; i < NPAR; i++) {
        pBytes[i] = LFSR[i];
      }
      build_codeword(msg, nbytes, out dst);
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Encode Parity
    //    エンコード関数 パリティ分離版
    public void encode_data_parity(char[] msg, int nbytes, out char[] Parity)
    {
      int i;
      int dbyte;
      int j;
      int[] LFSR;
      LFSR = new int[NPAR + 1];
      for (i = 0; i <= NPAR; i++) {
        LFSR[i] = 0;
      }
      for (i = 0; i < nbytes; i++) {
        dbyte = ((byte)msg[i]) ^ LFSR[NPAR - 1];
        for (j = NPAR - 1; j >= 1; j--) {
          LFSR[j] = LFSR[j - 1] ^ GT.gmult(genPoly[j], dbyte);
        }
        LFSR[0] = GT.gmult(genPoly[0], dbyte);
      }

      Parity = new char[NPAR];
      pBytes = new int[NPAR];
      for (i = 0; i < NPAR; i++) {
        Parity[i] = ((char)LFSR[i]);
      }
      // for i := 0 to NPAR-1 do Pareity := pBytes[i];

    }

    public short crc_ccitt(string msg, int leng)
    {
      short result = 0;
      return result;
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  correct errors erasures
    //    誤り訂正処理
    public int correct_errors_erasures(ref char[] codeword, int csize, int nerasures, int[] erasures)
    {
      int result;
      int r;
      int i;
      int j;
      byte err;
      int num;
      int denom;
      FNErasures = nerasures;
      for (i = 0; i < nerasures; i++) {
        ErasureLocs[i] = erasures[i];
      }
      Modified_Berlekamp_Massey();
      Find_Roots();
      if ((NErrors <= NPAR) && (NErrors > 0)) {
        // /* first check for illegal error locs */
        for (r = 0; r < NErrors; r++) {
          if (ErrorLocs[r] >= csize) {
            result = 0;
            return result;
          }
        }
        for (r = 0; r < NErrors; r++) {
          i = ErrorLocs[r];
          // /* evaluate Omega at alpha^(-i) */
          num = 0;
          for (j = 0; j < MAXDEG; j++) {
            num = num ^ GT.gmult(Omega[j], GT.gexp[((255 - i) * j) % 255]);
          }
          // /* evaluate Lambda' (derivative) at alpha^(-i) ; all odd powers disappear */
          denom = 0;
          j = 1;
          while ((j < MAXDEG)) {
            denom = denom ^ GT.gmult(Lambda[j], GT.gexp[((255 - i) * (j - 1)) % 255]);
            j += 2;
          }
          err = (byte)GT.gmult(num, GT.ginv(denom));
          //codeword[csize - i - 1] = ((char)((byte)codeword[csize - i - 1]) ^ err);
          byte b = (byte)codeword[csize - i - 1];
          b = (byte)(b ^ err);
          codeword[csize - i - 1] = (char)b;
        }
        result = 1;
        return result;
      }
      else {
        result = 0;
      }
      return result;
    }

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //  Compute GenPoly
    //    誤り訂正関数作成
    //    誤り訂正関数はエンコード時のみ使用される
    protected void compute_genpoly(int nbytes, out int[] genpoly)
    {
      genpoly = new int[0];

      int i;
      int[] tp = new int[255 + 1];
      int[] tp1 = new int[255 + 1];
      // /* multiply (x + a^n) for n = 1 to nbytes */
      zero_poly(out tp1);
      tp1[0] = 1;
      for (i = 1; i <= nbytes; i++) {
        zero_poly(out tp);
        tp[0] = GT.gexp[i];
        // * set up x+a^n */
        tp[1] = 1;
        mult_polys(out genpoly, tp, tp1);
        copy_poly(out tp1, genpoly);
      }
      // QRコード用 誤り訂正多項式
      // for i := 0 to nbytes do begin
      // genpoly[i]:=GT.gexp[GT.glog[genpoly[i]] - (nbytes-i)];
      // end;

    }

    protected void build_codeword(char[] msg, int nbytes, out char[] dst)
    {
      int i;
      dst = new char[nbytes];
      for (i = 0; i < nbytes; i++) {
        dst[i] = msg[i];
      }
      for (i = 0; i < NPAR; i++) {
        dst[i + nbytes] = ((char)pBytes[NPAR - 1 - i]);
      }
    }

    protected void Modified_Berlekamp_Massey()
    {
      int n;
      int l;
      int l2;
      int k;
      int d;
      int i;
      int[] psi;
      int[] psi2;
      int[] DA;
      int[] gamma;
      psi = new int[MAXDEG];
      psi2 = new int[MAXDEG];
      DA = new int[MAXDEG];
      gamma = new int[MAXDEG];
      // /* initialize Gamma, the erasure locator polynomial */
      init_gamma(out gamma);
      // /* initialize to z */
      copy_poly(out DA, gamma);
      mul_z_poly(ref DA);
      copy_poly(out psi, gamma);
      k = -1;
      l = FNErasures;
      for (n = FNErasures; n < NPAR; n++) {
        // for n:=FNErasures to 8-1 do begin
        d = compute_discrepancy(psi, synBytes, l, n);
        if (d != 0) {
          // /* psi2 = psi - d*D */
          for (i = 0; i < MAXDEG; i++) {
            psi2[i] = psi[i] ^ GT.gmult(d, DA[i]);
          }
          if (l < (n - k)) {
            l2 = n - k;
            k = n - l;
            // /* D = scale_poly(ginv(d), psi); */
            for (i = 0; i < MAXDEG; i++) {
              DA[i] = GT.gmult(psi[i], GT.ginv(d));
            }
            l = l2;
          }
          // /* psi = psi2 */
          for (i = 0; i < MAXDEG; i++) {
            psi[i] = psi2[i];
          }
        }
        mul_z_poly(ref DA);
      }
      // λの初期化
      Lambda = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        Lambda[i] = psi[i];
      }
      compute_modified_omega();
    }

    // * gamma = product (1-z*a^Ij) for erasure locs Ij */
    protected void init_gamma(out int[] gamma)
    {
      int e;
      int[] tmp;
      tmp = new int[MAXDEG];
      zero_poly(out gamma);
      zero_poly(out tmp);
      gamma[0] = 1;
      for (e = 0; e < FNErasures; e++) {
        copy_poly(out tmp, gamma);
        scale_poly(GT.gexp[ErasureLocs[e]], out tmp);
        mul_z_poly(ref tmp);
        add_polys(out gamma, tmp);
      }
    }

    protected int compute_discrepancy(int[] lambda, int[] S, int L, int n)
    {
      int result;
      int i;
      int sum;
      sum = 0;
      for (i = 0; i <= L; i++) {
        sum = sum ^ GT.gmult(lambda[i], S[n - i]);
      }
      result = sum;
      return result;
    }

    protected void compute_modified_omega()
    {
      int i;
      int[] product;
      product = new int[MAXDEG * 2];
      mult_polys(out product, Lambda, synBytes);
      // ωの初期化 (0でクリア後 productで初期値を代入)
      Omega = new int[MAXDEG];
      zero_poly(out Omega);
      for (i = 0; i < NPAR; i++) {
        Omega[i] = product[i];
      }
      //this.Finalize(product);
    }

    protected void Find_Roots()
    {
      int sum;
      int r;
      int k;
      NErrors = 0;
      for (r = 1; r < 256; r++) {
        sum = 0;
        // /* evaluate lambda at r */
        for (k = 0; k < NPAR + 1; k++) {
          sum = sum ^ GT.gmult(GT.gexp[(k * r) % 255], Lambda[k]);
        }
        if ((sum == 0)) {
          ErrorLocs[NErrors] = 255 - r;
          NErrors++;
        }
      }
    }

    public void zero_poly(out int[] poly)
    {
      int i;
      poly = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        poly[i] = 0;
      }
    }

    public void copy_poly(out int[] dst, int[] src)
    {
      int i;
      dst = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        dst[i] = src[i];
      }
    }

    public void add_polys(out int[] dst, int[] src)
    {
      int i;
      dst = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        dst[i] = dst[i] ^ src[i];
      }
    }

    // /* multiply by z, i.e., shift right by 1 */
    protected void mul_z_poly(ref int[] src)
    {
      int i;
      src = new int[MAXDEG - 1];
      for (i = MAXDEG - 1; i >= 1; i--) {
        src[i] = src[i - 1];
      }
      src[0] = 0;
    }

    public void scale_poly(int k, out int[] poly)
    {
      int i;
      poly = new int[MAXDEG];
      for (i = 0; i < MAXDEG; i++) {
        poly[i] = GT.gmult(k, poly[i]);
      }
    }

    public void mult_polys(out int[] dst, int[] p1, int[] p2)
    {
      int i;
      int j;
      int[] tmp1;
      tmp1 = new int[MAXDEG * 2];

      dst = new int[MAXDEG * 2];
      for (i = 0; i < (MAXDEG * 2); i++) {
        dst[i] = 0;
      }

      for (i = 0; i < MAXDEG; i++) {
        for (j = MAXDEG; j < (MAXDEG * 2); j++) {
          tmp1[j] = 0;
        }
        // /* scale tmp1 by p1[i] */
        for (j = 0; j < MAXDEG; j++) {
          tmp1[j] = GT.gmult(p2[j], p1[i]);
        }
        // /* and mult (shift) tmp1 right by i */
        j = (MAXDEG * 2) - 1;
        while ((j >= i)) {
          tmp1[j] = tmp1[j - i];
          j -= 1;
        }
        for (j = 0; j < i; j++) {
          tmp1[j] = 0;
        }
        // /* add into partial product */
        for (j = 0; j < (MAXDEG * 2); j++) {
          dst[j] = dst[j] ^ tmp1[j];
        }
      }
    }
  } // end TiPentecReedSolomonCodec
}

著者
iPentec Document 編集部
iPentec Document 編集部です。
快適な生活のための情報、価値のある体験やレビューを提供します。
最終更新日: 2024-01-24
改訂日: 2022-06-06
作成日: 2010-01-25
iPentec all rights reserverd.