diff --git a/src/Numerics/LinearAlgebra/Generic/SquareMatrix.cs b/src/Numerics/LinearAlgebra/Double/SquareMatrix.cs similarity index 65% rename from src/Numerics/LinearAlgebra/Generic/SquareMatrix.cs rename to src/Numerics/LinearAlgebra/Double/SquareMatrix.cs index ca4ba3e2..fc856e6f 100644 --- a/src/Numerics/LinearAlgebra/Generic/SquareMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/SquareMatrix.cs @@ -1,18 +1,15 @@ -namespace MathNet.Numerics.LinearAlgebra.Generic +namespace MathNet.Numerics.LinearAlgebra.Double { using System; using MathNet.Numerics.LinearAlgebra.Storage; - - using Properties; + using MathNet.Numerics.Properties; /// /// Abstract class for square matrices. /// - /// Supported data types are double, single, , and . [Serializable] - public abstract class SquareMatrix : Matrix - where T : struct, IEquatable, IFormattable + public abstract class SquareMatrix : Matrix { /// /// Number of rows or columns. @@ -20,12 +17,12 @@ protected readonly int Order; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// If the matrix is not square. /// - protected SquareMatrix(MatrixStorage storage) + protected SquareMatrix(MatrixStorage storage) : base(storage) { if (storage.RowCount != storage.ColumnCount) diff --git a/src/Numerics/LinearAlgebra/Double/SymmetricMatrix.cs b/src/Numerics/LinearAlgebra/Double/SymmetricMatrix.cs new file mode 100644 index 00000000..c6c94332 --- /dev/null +++ b/src/Numerics/LinearAlgebra/Double/SymmetricMatrix.cs @@ -0,0 +1,380 @@ +namespace MathNet.Numerics.LinearAlgebra.Double +{ + using System; + + using MathNet.Numerics.Distributions; + using MathNet.Numerics.LinearAlgebra.Generic; + using MathNet.Numerics.LinearAlgebra.Storage; + + /// + /// Abstract class for symmetric matrices. + /// + [Serializable] + public abstract class SymmetricMatrix : SquareMatrix + { + /// + /// Initializes a new instance of the class. + /// + protected SymmetricMatrix(MatrixStorage storage) + : base(storage) + { + } + + /// + /// Returns a value indicating whether the array is symmetric. + /// + /// + /// The array to check for symmetry. + /// + /// + /// True is array is symmetric, false if not symmetric. + /// + public static bool CheckIfSymmetric(double[,] array) + { + var rows = array.GetLength(0); + var columns = array.GetLength(1); + + if (rows != columns) + { + return false; + } + + for (var row = 0; row < rows; row++) + { + for (var column = 0; column < columns; column++) + { + if (column >= row) + { + continue; + } + + if (!array[row, column].Equals(array[column, row])) + { + return false; + } + } + } + + return true; + } + + /// + /// Gets a value indicating whether this matrix is symmetric. + /// + public override sealed bool IsSymmetric + { + get + { + return true; + } + } + + /// + /// Returns the transpose of this matrix. The transpose is equal and this method returns a reference to this matrix. + /// + /// + /// The transpose of this matrix. + /// + public override sealed Matrix Transpose() + { + return this; + } + + /// + /// Adds another matrix to this matrix. + /// + /// + /// The matrix to add to this matrix. + /// + /// + /// The matrix to store the result of the addition. + /// + /// + /// If the other matrix is . + /// + /// + /// If the two matrices don't have the same dimensions. + /// + protected override void DoAdd(Matrix other, Matrix result) + { + var symmetricOther = other as SymmetricMatrix; + var symmetricResult = result as SymmetricMatrix; + if (symmetricOther == null || symmetricResult == null) + { + base.DoAdd(other, result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column < ColumnCount; column++) + { + symmetricResult.At(row, column, At(row, column) + symmetricOther.At(row, column)); + } + } + } + } + + /// + /// Subtracts another matrix from this matrix. + /// + /// + /// The matrix to subtract to this matrix. + /// + /// + /// The matrix to store the result of subtraction. + /// + /// + /// If the other matrix is . + /// + /// + /// If the two matrices don't have the same dimensions. + /// + protected override void DoSubtract(Matrix other, Matrix result) + { + var symmetricOther = other as SymmetricMatrix; + var symmetricResult = result as SymmetricMatrix; + if (symmetricOther == null || symmetricResult == null) + { + base.DoSubtract(other, result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column < ColumnCount; column++) + { + symmetricResult.At(row, column, At(row, column) - symmetricOther.At(row, column)); + } + } + } + } + + /// + /// Multiplies each element of the matrix by a scalar and places results into the result matrix. + /// + /// + /// The scalar to multiply the matrix with. + /// + /// + /// The matrix to store the result of the multiplication. + /// + protected override void DoMultiply(double scalar, Matrix result) + { + var symmetricResult = result as SymmetricMatrix; + + if (symmetricResult == null) + { + base.DoMultiply(scalar, result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column < ColumnCount; column++) + { + symmetricResult.At(row, column, At(row, column) * scalar); + } + } + } + } + + /// + /// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix. + /// + /// + /// The matrix to multiply with. + /// + /// + /// The result of the multiplication. + /// + protected override sealed void DoTransposeThisAndMultiply(Matrix other, Matrix result) + { + DoMultiply(other, result); + } + + /// + /// Multiplies the transpose of this matrix with a vector and places the results into the result vector. + /// + /// + /// The vector to multiply with. + /// + /// + /// The result of the multiplication. + /// + protected override sealed void DoTransposeThisAndMultiply(Vector rightSide, Vector result) + { + DoMultiply(rightSide, result); + } + + /// + /// Negate each element of this matrix and place the results into the result matrix. + /// + /// + /// The result of the negation. + /// + protected override void DoNegate(Matrix result) + { + var symmetricResult = result as SymmetricMatrix; + + if (symmetricResult == null) + { + base.DoNegate(result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column != ColumnCount; column++) + { + symmetricResult[row, column] = -At(row, column); + } + } + } + } + + /// + /// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix. + /// + /// + /// The matrix to pointwise multiply with this one. + /// + /// + /// The matrix to store the result of the pointwise multiplication. + /// + protected override void DoPointwiseMultiply(Matrix other, Matrix result) + { + var symmetricOther = other as SymmetricMatrix; + var symmetricResult = result as SymmetricMatrix; + if (symmetricOther == null || symmetricResult == null) + { + base.DoPointwiseMultiply(other, result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column < ColumnCount; column++) + { + symmetricResult.At(row, column, At(row, column) * symmetricOther.At(row, column)); + } + } + } + } + + /// + /// Pointwise divide this matrix by another matrix and stores the result into the result matrix. + /// + /// + /// The matrix to pointwise divide this one by. + /// + /// + /// The matrix to store the result of the pointwise division. + /// + protected override void DoPointwiseDivide(Matrix other, Matrix result) + { + var symmetricOther = other as SymmetricMatrix; + var symmetricResult = result as SymmetricMatrix; + if (symmetricOther == null || symmetricResult == null) + { + base.DoPointwiseDivide(other, result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column < ColumnCount; column++) + { + symmetricResult.At(row, column, At(row, column) / symmetricOther.At(row, column)); + } + } + } + } + + /// + /// Computes the modulus for each element of the matrix. + /// + /// + /// The divisor to use. + /// + /// + /// Matrix to store the results in. + /// + protected override void DoModulus(double divisor, Matrix result) + { + var symmetricResult = result as SymmetricMatrix; + + if (symmetricResult == null) + { + base.DoModulus(divisor, result); + } + else + { + for (var row = 0; row < RowCount; row++) + { + for (var column = row; column < ColumnCount; column++) + { + symmetricResult.At(row, column, At(row, column) % divisor); + } + } + } + } + + /// + /// Populates a matrix with random elements. + /// + /// + /// The matrix to populate. + /// + /// + /// Continuous Random Distribution to generate elements from. + /// + protected override void DoRandom(Matrix matrix, IContinuousDistribution distribution) + { + var symmetricMatrix = matrix as SymmetricMatrix; + + if (symmetricMatrix == null) + { + base.DoRandom(matrix, distribution); + } + else + { + for (var row = 0; row < matrix.RowCount; row++) + { + for (var column = row; column < matrix.ColumnCount; column++) + { + symmetricMatrix.At(row, column, distribution.Sample()); + } + } + } + } + + /// + /// Populates a matrix with random elements. + /// + /// + /// The matrix to populate. + /// + /// + /// Continuous Random Distribution to generate elements from. + /// + protected override void DoRandom(Matrix matrix, IDiscreteDistribution distribution) + { + var symmetricMatrix = matrix as SymmetricMatrix; + if (symmetricMatrix == null) + { + base.DoRandom(matrix, distribution); + } + else + { + for (var row = 0; row < matrix.RowCount; row++) + { + for (var column = row; column < matrix.ColumnCount; column++) + { + symmetricMatrix.At(row, column, distribution.Sample()); + } + } + } + } + } +} diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 64c39dbd..531cbd69 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -140,7 +140,8 @@ - + +