Пример #1
0
        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));
        }
Пример #2
0
        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);
        }
Пример #3
0
        //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);
        }