public static MatrixGField CreateParityOnlyMatrix(GFTable gfTable, int dataBlocksCount, int parityBlockCount) { int totalBlocks = dataBlocksCount + parityBlockCount; if (totalBlocks > 256) { throw new InvalidOperationException("A total of more then 256 blocks is not supported"); } var parityMatrixArray = new GField[parityBlockCount, dataBlocksCount]; var baseList = BaseGFCalculator.CalculateBase(gfTable).ToList(); //Copy parity part of the matrix for (uint row = 0; row < parityBlockCount; row++) { for (int column = 0; column < parityMatrixArray.GetLength(1); column++) { var val = baseList[column].Pow(row + 1); parityMatrixArray[row, column] = val; } } return(new MatrixGField(parityMatrixArray)); }
public static MatrixGField CreateParityMatrix2(GFTable gfTable, int dataBlocksCount, int parityBlockCount) { int totalBlocks = dataBlocksCount + parityBlockCount; if (totalBlocks > 256) { throw new InvalidOperationException("A total of more then 256 blocks is not supported"); } var parityMatrixArray = new GField[totalBlocks, dataBlocksCount]; var baseList = BaseGFCalculator.CalculateBase(gfTable).ToList(); var res = string.Join(",", baseList); //Copy parity part of the matrix for (int row = 0; row < totalBlocks; row++) { for (uint column = 0; column < parityMatrixArray.GetLength(1); column++) { var val = baseList[row].Pow(column + 1); //var val = gfTable.CreateField(gfTable.Pow(2, gfTable.Mul(row, column))); //var val = baseList[row].Pow(gfTable.Mul(row, (uint)column)); parityMatrixArray[row, column] = val; } } var transposedVanDerMondeMatrix = new MatrixGField(parityMatrixArray); var dataMatrix = transposedVanDerMondeMatrix.Submatrix(0, dataBlocksCount - 1, 0, dataBlocksCount - 1); var invertedDataMatrix = dataMatrix.InverseRuben(); var finalMatrix = transposedVanDerMondeMatrix * invertedDataMatrix; return(finalMatrix); }
//public static List<Block<byte>> GenerateParityData(GFTable gfTable, List<Block<byte>> dataBlocks, int parityBlockCount) //{ // int dataLengthInsideBlock = dataBlocks.First().Data.Length; // var parityMatrix = CreateParityOnlyMatrix(gfTable, dataBlocks.Count, parityBlockCount); // var parityDataList = new List<Block<byte>>(); // for (int i = 0; i < parityBlockCount; i++) // { // parityDataList.Add(new Block<byte>() { Data = new byte[dataLengthInsideBlock] }); // } // for (int i = 0; i < dataLengthInsideBlock; i++) // { // var data = new List<GField>(); // foreach (var dataBlock in dataBlocks) // { // var newField = gfTable.CreateField(dataBlock.Data[i]); // data.Add(newField); // } // var toArray = data.ToArray(); // var parityData = parityMatrix.Multiply(toArray); // for (int y = 0; y < parityDataList.Count; y++) // { // parityDataList[y].Data[i] = (byte)parityData[y].Value; // } // } // return parityDataList; //} public static MatrixGField CreateParityMatrixForRecovery <T>(GFTable gfTable, List <Block <T> > dataBlocks, List <Block <T> > parityBlocks) { // parpresent // datapresent datamissing datamissing parmissing // / | \ / | \ //parpresent | (ppi[row])| | | (ppi[row])| | //datamissing | ^ | I | | ^ | 0 | // |(dpi[col]) | | |(dmi[col]) | | // +---------------------+-------------+ +---------------------+-----------+ // | (pmi[row])| | | (pmi[row])| | //parmissing | ^ | 0 | | ^ | I | // |(dpi[col]) | | |(dmi[col]) | | // \ | / \ | / uint datamissing = (uint)dataBlocks.Count(t => t.Data == null); uint parmissing = (uint)parityBlocks.Count(t => t.Data == null); uint datapresent = (uint)dataBlocks.Count(t => t.Data != null); uint parpresent = (uint)parityBlocks.Count(t => t.Data != null); uint outcount = datamissing + parmissing; uint incount = datapresent + datamissing; if (datamissing > parpresent) { throw new InvalidOperationException("Not enough recovery blocks."); } else if (outcount == 0) { throw new InvalidOperationException("No output blocks."); } int[] datamissingindex = new int[datamissing]; int[] parmissingindex = new int[parmissing]; int[] datapresentindex = new int[datapresent]; int[] parpresentindex = new int[parpresent]; int counterDataMissing = 0; int counterDataPresent = 0; for (int i = 0; i < dataBlocks.Count; i++) { var dataBlock = dataBlocks[i]; if (dataBlock.Data == null) { datamissingindex[counterDataMissing] = i; counterDataMissing++; } else { datapresentindex[counterDataPresent] = i; counterDataPresent++; } } int counterParMissing = 0; int counterParPresent = 0; for (int i = 0; i < parityBlocks.Count; i++) { var ParBlock = parityBlocks[i]; if (ParBlock.Data == null) { parmissingindex[counterParMissing] = i; counterParMissing++; } else { parpresentindex[counterParPresent] = i; counterParPresent++; } } var leftmatrix = new GField[outcount, incount]; var rightmatrix = new GField[outcount, outcount]; var combinedData = dataBlocks.Concat(parityBlocks).ToList(); int outputrow = 0; var database = BaseGFCalculator.CalculateBase(gfTable).ToList(); for (uint row = 0; row < datamissing; row++) { // Get the exponent of the next present recovery block while (combinedData[outputrow].Data != null) { outputrow++; } var exponent = (uint)outputrow; // One column for each present data block for (uint col = 0; col < datapresent; col++) { leftmatrix[row, col] = database[datapresentindex[col]].Pow((uint)parpresentindex[row]); } // One column for each each present recovery block that will be used for a missing data block for (uint col = 0; col < datamissing; col++) { leftmatrix[row, col + datapresent] = gfTable.CreateField((uint)((row == col) ? 1 : 0)); } if (datamissing > 0) { // One column for each missing data block for (uint col = 0; col < datamissing; col++) { rightmatrix[row, col] = database[datamissingindex[col]].Pow((uint)parpresentindex[row]); } // One column for each missing recovery block for (uint col = 0; col < parmissing; col++) { rightmatrix[row, col + datamissing] = gfTable.CreateField(0); } } outputrow++; } outputrow = 0; for (uint row = 0; row < parmissing; row++) { // Get the exponent of the next missing recovery block while (combinedData[outputrow].Data == null) { outputrow++; } var exponent = (uint)outputrow; // One column for each present data block for (uint col = 0; col < datapresent; col++) { leftmatrix[(row + datamissing), col] = database[datapresentindex[col]].Pow((uint)parmissingindex[row]); } // One column for each each present recovery block that will be used for a missing data block for (uint col = 0; col < datamissing; col++) { leftmatrix[(row + datamissing), col + datapresent] = gfTable.CreateField(0); } if (datamissing > 0) { // One column for each missing data block for (uint col = 0; col < datamissing; col++) { rightmatrix[(row + datamissing), col] = database[datamissingindex[col]].Pow((uint)parmissingindex[row]); } // One column for each missing recovery block for (uint col = 0; col < parmissing; col++) { rightmatrix[(row + datamissing), col + datamissing] = gfTable.CreateField((uint)((row == col) ? 1 : 0)); } } outputrow++; } var leftmatrixM = new MatrixGField(leftmatrix); var rightmatrixM = new MatrixGField(rightmatrix); if (datamissing > 0) { // Perform Gaussian Elimination and then delete the right matrix (which // will no longer be required). GaussElim(gfTable, outcount, incount, leftmatrixM, rightmatrixM, datamissing); } return(leftmatrixM); }