/// <summary>Constructs a matrix of the given size and assigns a given value to all diagonal elements.</summary> /// <param name="rows">Number of rows.</param> /// <param name="columns">Number of columns.</param> /// <param name="value">Value to assign to the diagnoal elements.</param> public MatrixGField(int rows, int columns, GField value) : this(rows, columns) { for (int i = 0; i < rows; i++) { Data[i][i] = value; } }
/// <summary> /// Multiply current Polynomial to anotherone. /// </summary> /// <returns>Result polynomial after multiply</returns> internal Polynomial Multiply(Polynomial other) { if (Primitive != other.Primitive) { throw new ArgumentException("Polynomial cannot perform Multiply as they do not have same Primitive for GaloisField256"); } if (IsMonomialZero || other.IsMonomialZero) { return(new Polynomial(GField, new int[] { 0 })); } int[] aCoefficients = Coefficients; int aLength = aCoefficients.Length; int[] bCoefficient = other.Coefficients; int bLength = bCoefficient.Length; int[] rCoefficients = new int[aLength + bLength - 1]; for (int aIndex = 0; aIndex < aLength; aIndex++) { int aCoeff = aCoefficients[aIndex]; for (int bIndex = 0; bIndex < bLength; bIndex++) { rCoefficients[aIndex + bIndex] = GField.Addition(rCoefficients[aIndex + bIndex], GField.Product(aCoeff, bCoefficient[bIndex])); } } return(new Polynomial(GField, rCoefficients)); }
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)); }
/// <summary> /// divide current polynomial by "other" /// </summary> /// <param name="other">The other.</param> /// <returns>Result polynomial after divide</returns> /// <remarks></remarks> internal PolyDivideStruct Divide(Polynomial other) { if (Primitive != other.Primitive) { throw new ArgumentException( "Polynomial can not perform Devide as they don't have same Primitive for GaloisField256"); } if (other.isMonomialZero) { throw new ArgumentException("Can not devide by Polynomial Zero"); } //this devide by other = a devide by b int aLength = Coefficients.Length; //We will make change to aCoefficient. It will return as remainder var aCoefficients = new int[aLength]; Array.Copy(Coefficients, 0, aCoefficients, 0, aLength); int bLength = other.Coefficients.Length; if (aLength < bLength) { return(new PolyDivideStruct(new Polynomial(GField, new[] { 0 }), this)); } else { //quotient coefficients //qLastIndex = alength - blength qlength = qLastIndex + 1 var qCoefficients = new int[(aLength - bLength) + 1]; //Denominator int otherLeadingTerm = other.GetCoefficient(other.Degree); int inverseOtherLeadingTerm = GField.inverse(otherLeadingTerm); for (int aIndex = 0; aIndex <= aLength - bLength; aIndex++) { if (aCoefficients[aIndex] != 0) { int aScalar = GField.Product(inverseOtherLeadingTerm, aCoefficients[aIndex]); Polynomial term = other.MultiplyScalar(aScalar); qCoefficients[aIndex] = aScalar; int[] bCoefficient = term.Coefficients; if (bCoefficient[0] != 0) { for (int bIndex = 0; bIndex < bLength; bIndex++) { aCoefficients[aIndex + bIndex] = GField.Subtraction(aCoefficients[aIndex + bIndex], bCoefficient[bIndex]); } } } } return(new PolyDivideStruct(new Polynomial(GField, qCoefficients), new Polynomial(GField, aCoefficients))); } }
/// <summary>Constructs an empty matrix of the given size.</summary> /// <param name="rows">Number of rows.</param> /// <param name="columns">Number of columns.</param> private MatrixGField(int rows, int columns) { this.Rows = rows; this.Columns = columns; Data = new GField[rows][]; for (int i = 0; i < rows; i++) { Data[i] = new GField[columns]; } }
internal Polynomial CoefficientXor(int[] smallerCoefficients, int[] largerCoefficients) { if (smallerCoefficients.Length > largerCoefficients.Length) { throw new ArgumentException("Can not perform CoefficientXor method as smaller Coefficients length is larger than larger one."); } int targetLength = largerCoefficients.Length; int[] xorCoefficient = new int[targetLength]; int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length; Array.Copy(largerCoefficients, 0, xorCoefficient, 0, lengthDiff); for (int index = lengthDiff; index < targetLength; index++) { xorCoefficient[index] = GField.Addition(largerCoefficients[index], smallerCoefficients[index - lengthDiff]); } return(new Polynomial(GField, xorCoefficient)); }
/// <summary> /// Multiplay scalar to current polynomial /// </summary> /// <param name="scalar">The scalar.</param> /// <returns>result of polynomial after multiply scalar</returns> /// <remarks></remarks> internal Polynomial MultiplyScalar(int scalar) { if (scalar == 0) { return(new Polynomial(GField, new[] { 0 })); } else if (scalar == 1) { return(this); } int length = Coefficients.Length; var rCoefficient = new int[length]; for (int index = 0; index < length; index++) { rCoefficient[index] = GField.Product(Coefficients[index], scalar); } return(new Polynomial(GField, rCoefficient)); }
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); }