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 @@
-
+
+