private static MatrixPart Operation(MatrixPart first, MatrixPart second, MatrixOperation operation) { if (second == null || first == null) { throw new ArgumentException("Matrix shouldn't be null"); } var mSizeFirst = MathExtensions.GetMatrixSize(first.Data); var mSizeSecond = MathExtensions.GetMatrixSize(second.Data); if (mSizeFirst.height != mSizeFirst.width || mSizeFirst.height != mSizeSecond.height || mSizeSecond.height != mSizeSecond.width) { throw new ArgumentException("Matrix should be square"); } var result = new int[mSizeFirst.height, mSizeFirst.height]; for (var i = 0; i < mSizeFirst.height; i++) { for (var j = 0; j < mSizeFirst.height; j++) { if (operation == MatrixOperation.Summation) { result[i, j] = first.Data[i, j] + second.Data[i, j]; } else { result[i, j] = first.Data[i, j] - second.Data[i, j]; } } } return(new MatrixPart(result)); }
public static int[,] Strassen(int[,] first, int[,] second) { if (!MathExtensions.IsEqualDimension(first, second)) { throw new ArgumentException("Matrixs are not square"); } var sourceDimension1 = MathExtensions.GetMatrixSize(first); int[,] firstPower2, secondPower2; var isPowerOf2 = MathExtensions.IsPowerOfTwo(sourceDimension1.height); if (isPowerOf2) { firstPower2 = first; secondPower2 = second; } else { firstPower2 = MathExtensions.CreateSquareMatrixPower2(first); secondPower2 = MathExtensions.CreateSquareMatrixPower2(second); } var result = StrassenInner(firstPower2, secondPower2); if (isPowerOf2) { return(result); } return(MathExtensions.CutNonsignificant0(result, sourceDimension1.height)); }
public static int[,] Classic(int[,] first, int[,] second) { if (first == null || second == null) { throw new ArgumentException("Matrixs are not consistent"); } var sizeFirst = MathExtensions.GetMatrixSize(first); var sizeSecond = MathExtensions.GetMatrixSize(second); if (sizeFirst.width != sizeSecond.height) { throw new ArgumentException("Matrixs are not consistent"); } var values = new int[sizeFirst.height, sizeSecond.width]; for (var j = 0; j < sizeSecond.width; j++) { for (var i = 0; i < sizeFirst.height; i++) { for (var r = 0; r < sizeFirst.width; r++) { values[i, j] += first[i, r] * second[r, j]; } } } return(values); }
public static bool IsMatrixSquare(int[,] matrix) { if (matrix == null) { return(false); } var sourceDimension = MathExtensions.GetMatrixSize(matrix); return(sourceDimension.height == sourceDimension.width); }
private static int[,] StrassenInner(int[,] firstPower2, int[,] secondPower2) { var sizes = MathExtensions.GetMatrixSize(firstPower2); var values = new int[sizes.height, sizes.width]; /* todo: идея : разделить матрицы на 4 подматрицы с размером n/2 * n/2 * вычислить 10 подматриц с операциями сложения-вычитания firstPower2[0, 0] + firstPower2[1, 1] * если размер матрицы = 1, то выполнить скалярное умножение * иначе рекурсивно делить матрицы на подматрицы дальше */ var a11 = new MatrixPart(firstPower2, PartOfMatrix.LeftTop); var a12 = new MatrixPart(firstPower2, PartOfMatrix.RightTop); var a21 = new MatrixPart(firstPower2, PartOfMatrix.LeftBottom); var a22 = new MatrixPart(firstPower2, PartOfMatrix.RightBottom); var b11 = new MatrixPart(secondPower2, PartOfMatrix.LeftTop); var b12 = new MatrixPart(secondPower2, PartOfMatrix.RightTop); var b21 = new MatrixPart(secondPower2, PartOfMatrix.LeftBottom); var b22 = new MatrixPart(secondPower2, PartOfMatrix.RightBottom); var s1 = b12 - b22; var s2 = a11 + a12; var s3 = a21 + a22; var s4 = b21 - b11; var s5 = a11 + a22; var s6 = b11 + b22; var s7 = a12 - a22; var s8 = b21 + b22; var s9 = a11 - a21; var s10 = b11 + b12; var p1 = ChooseMultiplicationAlgorithm(a11, s1); var p2 = ChooseMultiplicationAlgorithm(s2, b22); var p3 = ChooseMultiplicationAlgorithm(s3, b11); var p4 = ChooseMultiplicationAlgorithm(a22, s4); var p5 = ChooseMultiplicationAlgorithm(s5, s6); var p6 = ChooseMultiplicationAlgorithm(s7, s8); var p7 = ChooseMultiplicationAlgorithm(s9, s10); var c11 = p5 + p4 - p2 + p6; var c12 = p1 + p2; var c21 = p3 + p4; var c22 = p5 + p1 - p3 - p7; var result = MathExtensions.Join(c11.Data, c12.Data, c21.Data, c22.Data); return(result); }
// метод Штрассена умножает только квадратные матрицы public static int[,] CreateSquareMatrixPower2(int[,] values) { if (!IsMatrixSquare(values)) { throw new ArgumentException("Matrix is not square"); } var sourceDimension = MathExtensions.GetMatrixSize(values); var dimension = IsPowerOfTwo(sourceDimension.height) ? sourceDimension.height : GetNearestGreater2Power(sourceDimension.height); var resultMatrix = new int[dimension, dimension]; for (var i = 0; i < sourceDimension.height; i++) { for (var j = 0; j < sourceDimension.height; j++) { resultMatrix[i, j] = values[i, j]; } } return(resultMatrix); }