public static void encodeParity(this ReedSolomon reedSolomon, IByteBuffer[] shards, int offset, int byteCount) { // Check arguments. reedSolomon.checkBuffersAndSizes(shards, offset, byteCount); // Build the array of output buffers. IByteBuffer[] outputs = new IByteBuffer [reedSolomon.ParityShardCount]; Array.Copy(shards, reedSolomon.DataShardCount, outputs, 0, reedSolomon.ParityShardCount); // System.arraycopy(shards, dataShardCount, outputs, 0, parityShardCount); // Do the coding. LOOP.codeSomeShards( reedSolomon.ParityRows, shards, reedSolomon.DataShardCount, outputs, reedSolomon.ParityShardCount, offset, byteCount); }
public static void decodeMissing(this ReedSolomon reedSolomon, IByteBuffer[] shards, bool[] shardPresent, int offset, int byteCount) { // Check arguments. reedSolomon.checkBuffersAndSizes(shards, offset, byteCount); // Quick check: are all of the shards present? If so, there's // nothing to do. int numberPresent = 0; for (int i = 0; i < reedSolomon.TotalShardCount; i++) { if (shardPresent[i]) { numberPresent += 1; } } if (numberPresent == reedSolomon.TotalShardCount) { // Cool. All of the shards data data. We don't // need to do anything. return; } // More complete sanity check if (numberPresent < reedSolomon.DataShardCount) { throw new Exception("Not enough shards present"); } // Pull out the rows of the matrix that correspond to the // shards that we have and build a square matrix. This // matrix could be used to generate the shards that we have // from the original data. // // Also, pull out an array holding just the shards that // correspond to the rows of the submatrix. These shards // will be the input to the decoding process that re-creates // the missing data shards. Matrix subMatrix = new Matrix(reedSolomon.DataShardCount, reedSolomon.DataShardCount); IByteBuffer[] subShards = new IByteBuffer[reedSolomon.DataShardCount]; { int subMatrixRow = 0; for (int matrixRow = 0; matrixRow < reedSolomon.TotalShardCount && subMatrixRow < reedSolomon.DataShardCount; matrixRow++) { if (shardPresent[matrixRow]) { for (int c = 0; c < reedSolomon.DataShardCount; c++) { subMatrix.set(subMatrixRow, c, reedSolomon.Matrix.get(matrixRow, c)); } subShards[subMatrixRow] = shards[matrixRow]; subMatrixRow += 1; } } } // Invert the matrix, so we can go from the encoded shards // back to the original data. Then pull out the row that // generates the shard that we want to decode. Note that // since this matrix maps back to the orginal data, it can // be used to create a data shard, but not a parity shard. Matrix dataDecodeMatrix = subMatrix.invert(); // Re-create any data shards that were missing. // // The input to the coding is all of the shards we actually // have, and the output is the missing data shards. The computation // is done using the special decode matrix we just built. IByteBuffer[] outputs = new IByteBuffer[reedSolomon.ParityShardCount]; byte[][] matrixRows = new byte [reedSolomon.ParityShardCount][]; int outputCount = 0; for (int iShard = 0; iShard < reedSolomon.DataShardCount; iShard++) { if (!shardPresent[iShard]) { outputs[outputCount] = shards[iShard]; matrixRows[outputCount] = dataDecodeMatrix.getRow(iShard); outputCount += 1; } } LOOP.codeSomeShards( matrixRows, subShards, reedSolomon.DataShardCount, outputs, outputCount, offset, byteCount); // Now that we have all of the data shards intact, we can // compute any of the parity that is missing. // // The input to the coding is ALL of the data shards, including // any that we just calculated. The output is whichever of the // data shards were missing. outputCount = 0; for (int iShard = reedSolomon.DataShardCount; iShard < reedSolomon.TotalShardCount; iShard++) { if (!shardPresent[iShard]) { outputs[outputCount] = shards[iShard]; matrixRows[outputCount] = reedSolomon.ParityRows[iShard - reedSolomon.DataShardCount]; outputCount += 1; } } LOOP.codeSomeShards( matrixRows, shards, reedSolomon.DataShardCount, outputs, outputCount, offset, byteCount); }