diff --git a/src/Numerics/LinearAlgebra/Complex/SymmetricMatrix.cs b/src/Numerics/LinearAlgebra/Complex/SymmetricMatrix.cs
index 2b29f837..ba6d712f 100644
--- a/src/Numerics/LinearAlgebra/Complex/SymmetricMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Complex/SymmetricMatrix.cs
@@ -33,7 +33,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
using Properties;
using Storage;
-
///
/// Abstract class for symmetric matrices.
///
diff --git a/src/Numerics/LinearAlgebra/Complex32/SquareMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SquareMatrix.cs
new file mode 100644
index 00000000..337a5118
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Complex32/SquareMatrix.cs
@@ -0,0 +1,62 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Complex32
+{
+ using System;
+ using Numerics;
+ using Properties;
+ using Storage;
+
+ ///
+ /// Abstract class for square matrices.
+ ///
+ [Serializable]
+ public abstract class SquareMatrix : Matrix
+ {
+ ///
+ /// Number of rows or columns.
+ ///
+ protected readonly int Order;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// If the matrix is not square.
+ ///
+ protected SquareMatrix(MatrixStorage storage)
+ : base(storage)
+ {
+ if (storage.RowCount != storage.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ Order = storage.RowCount;
+ }
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Complex32/SymmetricDenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SymmetricDenseMatrix.cs
new file mode 100644
index 00000000..7e62c4d7
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Complex32/SymmetricDenseMatrix.cs
@@ -0,0 +1,767 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Complex32
+{
+ using System;
+ using Numerics;
+ using Generic;
+ using MathNet.Numerics.Distributions;
+ using MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static;
+ using Properties;
+ using Storage;
+
+ ///
+ /// A Symmetric Matrix class with dense storage.
+ ///
+ /// The underlying storage is a one dimensional array in column-major order.
+ /// The Upper Triangle is stored(it is equal to the Lower Triangle)
+ [Serializable]
+ public class SymmetricDenseMatrix : SymmetricMatrix
+ {
+ readonly DenseColumnMajorSymmetricMatrixStorage _storage;
+
+ ///
+ /// Gets the matrix's data.
+ ///
+ /// The matrix's data.
+ readonly Complex32[] _data;
+
+ internal SymmetricDenseMatrix(DenseColumnMajorSymmetricMatrixStorage storage)
+ : base(storage)
+ {
+ _storage = storage;
+ _data = _storage.Data;
+ }
+
+ ///
+ /// Initializes a new instance of the class. This matrix is square with a given size.
+ ///
+ /// The order of the matrix.
+ ///
+ /// If is less than one.
+ ///
+ public SymmetricDenseMatrix(int order)
+ : this(new DenseColumnMajorSymmetricMatrixStorage(order))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with all entries set to a particular value.
+ ///
+ ///
+ /// The order of the matrix.
+ ///
+ /// The value which we assign to each element of the matrix.
+ public SymmetricDenseMatrix(int order, Complex32 value)
+ : this(order)
+ {
+ for (var i = 0; i < _data.Length; i++)
+ {
+ _data[i] = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class from a one dimensional array. This constructor
+ /// will reference the one dimensional array and not copy it.
+ ///
+ /// The size of the square matrix.
+ ///
+ /// The one dimensional array to create this matrix from. Column-major and row-major order is identical on a symmetric matrix: http://en.wikipedia.org/wiki/Row-major_order
+ ///
+ ///
+ /// If does not represent a packed array.
+ ///
+ public SymmetricDenseMatrix(int order, Complex32[] array)
+ : this(new DenseColumnMajorSymmetricMatrixStorage(order, array))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class from a 2D array. This constructor
+ /// will allocate a completely new memory block for storing the symmetric dense matrix.
+ ///
+ /// The 2D array to create this matrix from.
+ ///
+ /// If is not a square array.
+ ///
+ ///
+ /// If is not a symmetric array.
+ ///
+ public SymmetricDenseMatrix(Complex32[,] array)
+ : this(array.GetLength(0))
+ {
+ if (!CheckIfSymmetric(array))
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
+ }
+
+ var indexer = new PackedStorageIndexerUpper(Order);
+ for (var row = 0; row < Order; row++)
+ {
+ for (var column = row; column < Order; column++)
+ {
+ _data[indexer.Of(row, column)] = array[row, column];
+ }
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class, copying
+ /// the values from the given matrix. Matrix must be Symmetric.
+ ///
+ /// The matrix to copy.
+ ///
+ /// If is not a square matrix.
+ ///
+ ///
+ /// If is not a symmetric matrix.
+ ///
+ public SymmetricDenseMatrix(Matrix matrix)
+ : this(matrix.RowCount)
+ {
+ var symmetricMatrix = matrix as SymmetricDenseMatrix;
+
+ if (!matrix.IsSymmetric)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
+ }
+
+ if (symmetricMatrix == null)
+ {
+ var indexer = new PackedStorageIndexerUpper(Order);
+ for (var row = 0; row < Order; row++)
+ {
+ for (var column = row; column < Order; column++)
+ {
+ _data[indexer.Of(row, column)] = matrix[row, column];
+ }
+ }
+ }
+ else
+ {
+ matrix.CopyTo(this);
+ }
+ }
+
+ ///
+ /// Gets the matrix's data.
+ ///
+ /// The matrix's data.
+ public Complex32[] Data
+ {
+ get { return _data; }
+ }
+
+ ///
+ /// Creates a SymmetricDenseMatrix for the given number of rows and columns.
+ /// If rows and columns are not equal, returns a DenseMatrix instead.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ /// True if all fields must be mutable (e.g. not a diagonal matrix).
+ ///
+ /// A DenseMatrix or SymmetricDenseMatrix with the given dimensions.
+ ///
+ /// ///
+ /// If is not equal to .
+ /// Symmetric arrays are always square
+ ///
+ public override Matrix CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false)
+ {
+ if (numberOfRows != numberOfColumns || fullyMutable)
+ {
+ return new DenseMatrix(numberOfRows, numberOfColumns);
+ }
+
+ return new SymmetricDenseMatrix(numberOfRows);
+ }
+
+ ///
+ /// Creates a with a the given dimension.
+ ///
+ /// The size of the vector.
+ /// True if all fields must be mutable.
+ ///
+ /// A with the given dimension.
+ ///
+ public override Vector CreateVector(int size, bool fullyMutable = false)
+ {
+ return new DenseVector(size);
+ }
+
+ #region Static constructors for special matrices.
+
+ ///
+ /// Initializes a square with all zero's except for ones on the diagonal.
+ ///
+ /// the size of the square matrix.
+ /// A symmetric dense identity matrix.
+ ///
+ /// If is less than one.
+ ///
+ public static SymmetricDenseMatrix Identity(int order)
+ {
+ var m = new SymmetricDenseMatrix(order);
+ for (var i = 0; i < order; i++)
+ {
+ m.At(i, i, 1.0f);
+ }
+
+ return m;
+ }
+
+ #endregion
+
+ ///
+ /// Adds another matrix to this matrix.
+ ///
+ /// The matrix to add to this matrix.
+ /// The matrix to store the result of add
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ protected override void DoAdd(Matrix other, Matrix result)
+ {
+ var denseOther = other as SymmetricDenseMatrix;
+ var denseResult = result as SymmetricDenseMatrix;
+ if (denseOther == null || denseResult == null)
+ {
+ base.DoAdd(other, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.AddArrays(_data, denseOther._data, denseResult._data);
+ }
+ }
+
+ ///
+ /// Subtracts another matrix from this matrix.
+ ///
+ /// The matrix to subtract.
+ /// The matrix to store the result of the subtraction.
+ protected override void DoSubtract(Matrix other, Matrix result)
+ {
+ var denseOther = other as SymmetricDenseMatrix;
+ var denseResult = result as SymmetricDenseMatrix;
+ if (denseOther == null || denseResult == null)
+ {
+ base.DoSubtract(other, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.SubtractArrays(_data, denseOther._data, denseResult._data);
+ }
+ }
+
+ ///
+ /// 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(Complex32 scalar, Matrix result)
+ {
+ var denseResult = result as SymmetricDenseMatrix;
+ if (denseResult == null)
+ {
+ base.DoMultiply(scalar, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data);
+ }
+ }
+
+ ///
+ /// Multiplies 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 void DoMultiply(Vector rightSide, Vector result)
+ {
+ var denseRight = rightSide as DenseVector;
+ var denseResult = result as DenseVector;
+
+ if (denseRight == null || denseResult == null)
+ {
+ base.DoMultiply(rightSide, result);
+ }
+ else
+ {
+ // TODO: Change this when symmetric methods are implemented in the Linear Algebra Providers.
+ base.DoMultiply(rightSide, result);
+ }
+ }
+
+ ///
+ /// Multiplies 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 void DoMultiply(Matrix other, Matrix result)
+ {
+ var denseOther = other as SymmetricDenseMatrix;
+ var denseResult = result as SymmetricDenseMatrix;
+
+ if (denseOther == null || denseResult == null)
+ {
+ base.DoMultiply(other, result);
+ }
+ else
+ {
+ // TODO: Change this when symmetric methods are implemented in the Linear Algebra Providers.
+ base.DoMultiply(other, result);
+ }
+ }
+
+ ///
+ /// Multiplies this matrix with transpose of another matrix and places the results into the result matrix.
+ ///
+ /// The matrix to multiply with.
+ /// The result of the multiplication.
+ protected override void DoTransposeAndMultiply(Matrix other, Matrix result)
+ {
+ var denseOther = other as SymmetricDenseMatrix;
+ var denseResult = result as SymmetricDenseMatrix;
+
+ if (denseOther == null || denseResult == null)
+ {
+ base.DoTransposeAndMultiply(other, result);
+ }
+ else
+ {
+ // TODO: Change this when symmetric methods are implemented in the Linear Algebra Providers.
+ base.DoTransposeAndMultiply(other, 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 denseResult = result as SymmetricDenseMatrix;
+
+ if (denseResult == null)
+ {
+ base.DoNegate(result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data);
+ }
+ }
+
+ ///
+ /// 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 denseOther = other as SymmetricDenseMatrix;
+ var denseResult = result as SymmetricDenseMatrix;
+
+ if (denseOther == null || denseResult == null)
+ {
+ base.DoPointwiseMultiply(other, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_data, denseOther._data, denseResult._data);
+ }
+ }
+
+ ///
+ /// 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 denseOther = other as SymmetricDenseMatrix;
+ var denseResult = result as SymmetricDenseMatrix;
+
+ if (denseOther == null || denseResult == null)
+ {
+ base.DoPointwiseDivide(other, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.PointWiseDivideArrays(_data, denseOther._data, denseResult._data);
+ }
+ }
+
+ ///
+ /// Returns a new matrix containing the lower triangle of this matrix.
+ ///
+ /// The lower triangle of this matrix.
+ public override Matrix LowerTriangle()
+ {
+ var ret = new DenseMatrix(Order);
+ for (var row = 0; row < Order; row++)
+ {
+ for (var column = 0; column <= row; column++)
+ {
+ ret[row, column] = At(row, column);
+ }
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Returns a new matrix containing the lower triangle of this matrix. The new matrix
+ /// does not contain the diagonal elements of this matrix.
+ ///
+ /// The lower triangle of this matrix.
+ public override Matrix StrictlyLowerTriangle()
+ {
+ var ret = new DenseMatrix(Order);
+ for (var row = 0; row < Order; row++)
+ {
+ for (var column = 0; column < row; column++)
+ {
+ ret[row, column] = At(row, column);
+ }
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Returns a new matrix containing the upper triangle of this matrix.
+ ///
+ /// The upper triangle of this matrix.
+ public override Matrix UpperTriangle()
+ {
+ var ret = new DenseMatrix(Order);
+ for (var row = 0; row < Order; row++)
+ {
+ for (var column = row; column < Order; column++)
+ {
+ ret[row, column] = At(row, column);
+ }
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Returns a new matrix containing the upper triangle of this matrix. The new matrix
+ /// does not contain the diagonal elements of this matrix.
+ ///
+ /// The upper triangle of this matrix.
+ public override Matrix StrictlyUpperTriangle()
+ {
+ var ret = new DenseMatrix(Order);
+ for (var row = 0; row < Order; row++)
+ {
+ for (var column = row + 1; column < Order; column++)
+ {
+ ret[row, column] = At(row, column);
+ }
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Computes the trace of this matrix.
+ ///
+ /// The trace of this matrix
+ public override Complex32 Trace()
+ {
+ // Matrix is always square.
+ var sum = Complex32.Zero;
+ for (var i = 0; i < RowCount; i++)
+ {
+ sum += At(i, i);
+ }
+
+ return sum;
+ }
+
+ ///
+ /// Populates a symmetric matrix with random elements.
+ ///
+ /// The symmetric matrix to populate.
+ /// Continuous Random Distribution to generate elements from.
+ protected override void DoRandom(Matrix matrix, IContinuousDistribution distribution)
+ {
+ var denseMatrix = matrix as SymmetricDenseMatrix;
+
+ if (denseMatrix == null)
+ {
+ base.DoRandom(matrix, distribution);
+ }
+ else
+ {
+ for (var i = 0; i < denseMatrix._data.Length; i++)
+ {
+ denseMatrix._data[i] = Convert.ToSingle(distribution.Sample());
+ }
+ }
+ }
+
+ ///
+ /// Populates a symmetric matrix with random elements.
+ ///
+ /// The symmetric matrix to populate.
+ /// Continuous Random Distribution to generate elements from.
+ protected override void DoRandom(Matrix matrix, IDiscreteDistribution distribution)
+ {
+ var denseMatrix = matrix as SymmetricDenseMatrix;
+
+ if (denseMatrix == null)
+ {
+ base.DoRandom(matrix, distribution);
+ }
+ else
+ {
+ for (var i = 0; i < denseMatrix._data.Length; i++)
+ {
+ denseMatrix._data[i] = distribution.Sample();
+ }
+ }
+ }
+
+ ///
+ /// Adds two matrices together and returns the results.
+ ///
+ /// This operator will allocate new memory for the result. It will
+ /// choose the representation of either or depending on which
+ /// is denser.
+ /// The left matrix to add.
+ /// The right matrix to add.
+ /// The result of the addition.
+ /// If and don't have the same dimensions.
+ /// If or is .
+ public static SymmetricDenseMatrix operator +(SymmetricDenseMatrix leftSide, SymmetricDenseMatrix rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.RowCount != rightSide.RowCount)
+ {
+ throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);
+ }
+
+ return (SymmetricDenseMatrix)leftSide.Add(rightSide);
+ }
+
+ ///
+ /// Returns a Matrix containing the same values of .
+ ///
+ /// The matrix to get the values from.
+ /// A matrix containing a the same values as .
+ /// If is .
+ public static SymmetricDenseMatrix operator +(SymmetricDenseMatrix rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return (SymmetricDenseMatrix)rightSide.Clone();
+ }
+
+ ///
+ /// Subtracts two matrices together and returns the results.
+ ///
+ /// This operator will allocate new memory for the result. It will
+ /// choose the representation of either or depending on which
+ /// is denser.
+ /// The left matrix to subtract.
+ /// The right matrix to subtract.
+ /// The result of the addition.
+ /// If and don't have the same dimensions.
+ /// If or is .
+ public static SymmetricDenseMatrix operator -(SymmetricDenseMatrix leftSide, SymmetricDenseMatrix rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.RowCount != rightSide.RowCount)
+ {
+ throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);
+ }
+
+ return (SymmetricDenseMatrix)leftSide.Subtract(rightSide);
+ }
+
+ ///
+ /// Negates each element of the matrix.
+ ///
+ /// The matrix to negate.
+ /// A matrix containing the negated values.
+ /// If is .
+ public static SymmetricDenseMatrix operator -(SymmetricDenseMatrix rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return (SymmetricDenseMatrix)rightSide.Negate();
+ }
+
+ ///
+ /// Multiplies a Matrix by a constant and returns the result.
+ ///
+ /// The matrix to multiply.
+ /// The constant to multiply the matrix by.
+ /// The result of the multiplication.
+ /// If is .
+ public static SymmetricDenseMatrix operator *(SymmetricDenseMatrix leftSide, Complex32 rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ return (SymmetricDenseMatrix)leftSide.Multiply(rightSide);
+ }
+
+ ///
+ /// Multiplies a Matrix by a constant and returns the result.
+ ///
+ /// The matrix to multiply.
+ /// The constant to multiply the matrix by.
+ /// The result of the multiplication.
+ /// If is .
+ public static SymmetricDenseMatrix operator *(Complex32 leftSide, SymmetricDenseMatrix rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return (SymmetricDenseMatrix)rightSide.Multiply(leftSide);
+ }
+
+ ///
+ /// Multiplies two matrices.
+ ///
+ /// This operator will allocate new memory for the result. It will
+ /// choose the representation of either or depending on which
+ /// is denser.
+ /// The left matrix to multiply.
+ /// The right matrix to multiply.
+ /// The result of multiplication.
+ /// If or is .
+ /// If the dimensions of or don't conform.
+ public static SymmetricDenseMatrix operator *(SymmetricDenseMatrix leftSide, SymmetricDenseMatrix rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide.ColumnCount != rightSide.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ return (SymmetricDenseMatrix)leftSide.Multiply(rightSide);
+ }
+
+ ///
+ /// Multiplies a Matrix and a Vector.
+ ///
+ /// The matrix to multiply.
+ /// The vector to multiply.
+ /// The result of multiplication.
+ /// If or is .
+ public static DenseVector operator *(SymmetricDenseMatrix leftSide, DenseVector rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ return (DenseVector)leftSide.Multiply(rightSide);
+ }
+
+ ///
+ /// Multiplies a Vector and a Matrix.
+ ///
+ /// The vector to multiply.
+ /// The matrix to multiply.
+ /// The result of multiplication.
+ /// If or is .
+ public static DenseVector operator *(DenseVector leftSide, SymmetricDenseMatrix rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return (DenseVector)rightSide.LeftMultiply(leftSide);
+ }
+
+ ///
+ /// Multiplies a Matrix by a constant and returns the result.
+ ///
+ /// The matrix to multiply.
+ /// The constant to multiply the matrix by.
+ /// The result of the multiplication.
+ /// If is .
+ public static SymmetricDenseMatrix operator %(SymmetricDenseMatrix leftSide, Complex32 rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ return (SymmetricDenseMatrix)leftSide.Modulus(rightSide);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Numerics/LinearAlgebra/Complex32/SymmetricMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SymmetricMatrix.cs
new file mode 100644
index 00000000..099df458
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Complex32/SymmetricMatrix.cs
@@ -0,0 +1,711 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Complex32
+{
+ using System;
+ using Numerics;
+ using Generic;
+ using Distributions;
+ using Properties;
+ using 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(Complex32[,] 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.Clone();
+ }
+
+ ///
+ /// Adds another matrix to this matrix.
+ ///
+ /// The matrix to add to this matrix.
+ /// The result of the addition.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public override Matrix Add(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (other.RowCount != RowCount || other.ColumnCount != ColumnCount)
+ {
+ throw DimensionsDontMatch(this, other);
+ }
+
+ Matrix result;
+ if (other is SymmetricMatrix)
+ {
+ result = CreateMatrix(RowCount, ColumnCount);
+ }
+ else
+ {
+ result = CreateMatrix(RowCount, ColumnCount, true);
+ }
+
+ DoAdd(other, result);
+ return result;
+ }
+
+ ///
+ /// 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 (symmetricResult != null && !other.IsSymmetric)
+ {
+ throw new InvalidOperationException("Symmetric + non-symmetric matrix cannot be a symmetric matrix");
+ }
+
+ 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.
+ /// The result of the subtraction.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public override Matrix Subtract(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (other.RowCount != RowCount || other.ColumnCount != ColumnCount)
+ {
+ throw DimensionsDontMatch(this, other);
+ }
+
+ Matrix result;
+ if (other is SymmetricMatrix)
+ {
+ result = CreateMatrix(RowCount, ColumnCount);
+ }
+ else
+ {
+ result = CreateMatrix(RowCount, ColumnCount, true);
+ }
+
+ DoSubtract(other, result);
+ return result;
+ }
+
+
+ ///
+ /// 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 (symmetricResult != null && !other.IsSymmetric)
+ {
+ throw new InvalidOperationException("Symmetric - non-symmetric matrix cannot be a symmetric matrix");
+ }
+
+ 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(Complex32 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.
+ ///
+ /// The matrix to pointwise multiply with this one.
+ /// If the other matrix is .
+ /// If this matrix and are not the same size.
+ /// A new matrix that is the pointwise multiplication of this matrix and .
+ public override Matrix PointwiseMultiply(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
+ {
+ throw DimensionsDontMatch(this, other, "other");
+ }
+
+ Matrix result;
+ if (other is SymmetricMatrix)
+ {
+ result = CreateMatrix(RowCount, ColumnCount);
+ }
+ else
+ {
+ result = CreateMatrix(RowCount, ColumnCount, true);
+ }
+
+ PointwiseMultiply(other, result);
+ return result;
+ }
+
+ ///
+ /// 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 (symmetricResult != null && !other.IsSymmetric)
+ {
+ throw new InvalidOperationException("Symmetric pointwise* non-symmetric matrix cannot be a symmetric matrix");
+ }
+
+ 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.
+ ///
+ /// The matrix to pointwise subtract this one by.
+ /// If the other matrix is .
+ /// If this matrix and are not the same size.
+ /// A new matrix that is the pointwise division of this matrix and .
+ public override Matrix PointwiseDivide(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
+ {
+ throw DimensionsDontMatch(this, other);
+ }
+
+ Matrix result;
+ if (other is SymmetricMatrix)
+ {
+ result = CreateMatrix(RowCount, ColumnCount);
+ }
+ else
+ {
+ result = CreateMatrix(RowCount, ColumnCount, true);
+ }
+
+ PointwiseDivide(other, result);
+ return result;
+ }
+
+ ///
+ /// 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 (symmetricResult != null && !other.IsSymmetric)
+ {
+ throw new InvalidOperationException("Symmetric pointwise/ non-symmetric matrix cannot be a symmetric matrix");
+ }
+
+ 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(Complex32 divisor, Matrix result)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// 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, Convert.ToSingle(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());
+ }
+ }
+ }
+ }
+
+ ///
+ /// Creates a new matrix and inserts the given column at the given index.
+ ///
+ /// The index of where to insert the column.
+ /// The column to insert.
+ /// A new matrix with the inserted column.
+ /// If is .
+ /// If is < zero or > the number of columns.
+ /// If the size of != the number of rows.
+ public override Matrix InsertColumn(int columnIndex, Vector column)
+ {
+ throw new InvalidOperationException("Inserting a column is not supported on a symmetric matrix. Symmetric matrices are square");
+ }
+
+ ///
+ /// Copies the values of the given array to the specified column. The changes retain the symmetry of the matrix.
+ ///
+ /// The column to copy the values to.
+ /// The array to copy the values from.
+ /// If is .
+ /// If is less than zero,
+ /// or greater than or equal to the number of columns.
+ /// If the size of does not
+ /// equal the number of rows of this Matrix.
+ /// If the size of does not
+ /// equal the number of rows of this Matrix.
+ public override void SetColumn(int columnIndex, Complex32[] column)
+ {
+ if (columnIndex < 0 || columnIndex >= ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException("columnIndex");
+ }
+
+ if (column == null)
+ {
+ throw new ArgumentNullException("column");
+ }
+
+ if (column.Length != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "column");
+ }
+
+ for (var i = 0; i < columnIndex; i++)
+ {
+ At(i, columnIndex, column[i]);
+ }
+ }
+
+ ///
+ /// Copies the values of the given Vector to the specified column. The changes retain the symmetry of the matrix.
+ ///
+ /// The column to copy the values to.
+ /// The vector to copy the values from.
+ /// If is .
+ /// If is less than zero,
+ /// or greater than or equal to the number of columns.
+ /// If the size of does not
+ /// equal the number of rows of this Matrix.
+ public override void SetColumn(int columnIndex, Vector column)
+ {
+ if (columnIndex < 0 || columnIndex >= ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException("columnIndex");
+ }
+
+ if (column == null)
+ {
+ throw new ArgumentNullException("column");
+ }
+
+ if (column.Count != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "column");
+ }
+
+ for (var i = 0; i < columnIndex; i++)
+ {
+ At(i, columnIndex, column[i]);
+ }
+ }
+
+ ///
+ /// Creates a new matrix and inserts the given row at the given index.
+ ///
+ /// The index of where to insert the row.
+ /// The row to insert.
+ /// A new matrix with the inserted column.
+ /// If is .
+ /// If is < zero or > the number of rows.
+ /// If the size of != the number of columns.
+ public override Matrix InsertRow(int rowIndex, Vector row)
+ {
+ throw new InvalidOperationException("Inserting a row is not supported on a symmetric matrix. Symmetric matrices are square");
+ }
+
+ ///
+ /// Copies the values of the given Vector to the specified row.
+ ///
+ /// The row to copy the values to.
+ /// The vector to copy the values from.
+ /// If is .
+ /// If is less than zero,
+ /// or greater than or equal to the number of rows.
+ /// If the size of does not
+ /// equal the number of columns of this Matrix.
+ public override void SetRow(int rowIndex, Vector row)
+ {
+ if (rowIndex < 0 || rowIndex >= RowCount)
+ {
+ throw new ArgumentOutOfRangeException("rowIndex");
+ }
+
+ if (row == null)
+ {
+ throw new ArgumentNullException("row");
+ }
+
+ if (row.Count != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "row");
+ }
+
+ for (var i = rowIndex; i < ColumnCount; i++)
+ {
+ At(rowIndex, i, row[i]);
+ }
+ }
+
+ ///
+ /// Copies the values of the given array to the specified row.
+ ///
+ /// The row to copy the values to.
+ /// The array to copy the values from.
+ /// If is .
+ /// If is less than zero,
+ /// or greater than or equal to the number of rows.
+ /// If the size of does not
+ /// equal the number of columns of this Matrix.
+ public override void SetRow(int rowIndex, Complex32[] row)
+ {
+ if (rowIndex < 0 || rowIndex >= RowCount)
+ {
+ throw new ArgumentOutOfRangeException("rowIndex");
+ }
+
+ if (row == null)
+ {
+ throw new ArgumentNullException("row");
+ }
+
+ if (row.Length != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "row");
+ }
+
+ for (var i = rowIndex; i < ColumnCount; i++)
+ {
+ At(rowIndex, i, row[i]);
+ }
+ }
+ }
+}
diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index b0666824..6ea108fb 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -140,6 +140,9 @@
+
+
+