public CDRepair(int finalSampleCount, int stride, int npar) { this.npar = npar; this.stride = stride; this.finalSampleCount = finalSampleCount; sampleCount = 0; galois = Galois16.instance; rs = new RsDecode16(npar, galois); //crc32 = new Crc32(); //crc = 0xffffffff; encodeGx = galois.makeEncodeGxLog(npar); laststride = stride + (finalSampleCount * 2) % stride; stridecount = (finalSampleCount * 2) / stride - 2; // minus one for leadin and one for leadout if ((finalSampleCount * 2 + stride - 1) / stride + npar > galois.Max) throw new Exception("invalid stride"); }
/** * チェン探索により誤り位置を求める * σ(z) = 0の解を探索する * ただし、探索はデータ長以内の解のみで * jisu個の解が見つからなければ、エラーとする * @param pos int[] * 誤り位置格納用配列、jisu個の領域が必要 * @param n int * データ長 * @param jisu int * σの次数 * @param sigma int[] * σ0,σ1,σ2, ... σ<jisu> * @return int * 0: 正常終了 * < 0: エラー */ public unsafe bool chienSearch(int *pos, int n, int jisu, int *sigma) { /* * σ(z) = (1-α^i*z)(1-α^j*z)(1-α^k*z) * = 1 + σ1z + σ2z^2 +... * σ1 = α^i + α^j + α^k * つまりσ1は全ての解の合計となっている。上記の性質を利用して、プチ最適化 * last = σ1から、見つけた解を次々と引いていくことにより、最後の解はlastとなる */ int last = sigma[1]; if (jisu == 1) { // 次数が1ならばlastがその解である return(setLastErrorPos(pos, n, last)); } int *sg = stackalloc int[jisu + 1]; for (int j = 1; j <= jisu; j++) { sg[j] = sigma[j]; } int posIdx = jisu - 1; // 誤り位置格納用インデックス bool haveZeroes = false; // haveZeroes = true; for (int j = 1; j <= jisu; j++) { haveZeroes |= sg[j] == 0; } if (!haveZeroes && this.galois.Max == 0xffff) { const int himax = 0x11000; fixed(ushort *exp = this.galois.ExpTbl, log = this.galois.LogTbl) { for (int j = 1; j <= jisu; j++) { sg[j] = log[sg[j]] - ((j * n) % 0xffff) + 0xffff; sg[j] = (sg[j] & 0xffff) + (sg[j] >> 16); } int i = n; while (i > 0) { int cnt = i; for (int j = 1; j <= jisu; j++) { sg[j] = (sg[j] & 0xffff) + (sg[j] >> 16); cnt = Math.Min(cnt, (himax - sg[j]) / j); } i -= RsDecode.chienFast(sg, exp, cnt, jisu); int wk = 1; for (int j = 1; j <= jisu; j++) { wk ^= exp[sg[j]]; } if (wk == 0) { last ^= pos[posIdx--] = exp[i]; if (posIdx == 0) { pos[0] = last; return(log[last] < n); } } } } return(false); } for (int i = 0; i < n; i++) { /* * σ(z)の計算 * w を1(0乗の項)に初期化した後、残りの項<1..jisu>を加算 * z = 1/α^i = α^Iとすると * σ(z) = 1 + σ1α^I + σ2(α^I)^2 + σ3(α^I)^3 + ... + σ<jisu>/(α^I)^<jisu> * = 1 + σ1α^I + σ2α^(I*2) + σ3α^(I*3) + ... + σ<jisu>α^(I*<jisu>) */ int wk = 1; for (int j = 1; j <= jisu; j++) { wk ^= sg[j]; } for (int j = 1; j <= jisu; j++) { sg[j] = galois.divExp(sg[j], j); } if (wk == 0) { int pv = galois.toExp(i); // σ(z) = 0の解 last ^= pv; // lastから今見つかった解を引く pos[posIdx--] = pv; if (posIdx == 0) { // 残りが一つならば、lastがその解である return(setLastErrorPos(pos, n, last)); } } } // 探索によりデータ長以内に、jisu個の解が見つからなかった return(false); }