Compare commits
34 Commits
master
...
la-symmetr
| Author | SHA1 | Date |
|---|---|---|
|
|
68b34df6bd | 13 years ago |
|
|
148ac01b6f | 13 years ago |
|
|
e55400ef41 | 13 years ago |
|
|
38a8b1f01b | 13 years ago |
|
|
4cd1c829c5 | 13 years ago |
|
|
a5b9e7eabc | 13 years ago |
|
|
3654f3b3f0 | 13 years ago |
|
|
11ceb277b0 | 13 years ago |
|
|
d0b140acce | 13 years ago |
|
|
07f563d7e4 | 13 years ago |
|
|
938df8b594 | 13 years ago |
|
|
ba2665b7bf | 13 years ago |
|
|
3071d77337 | 13 years ago |
|
|
b2aa32c872 | 13 years ago |
|
|
94747be5f6 | 13 years ago |
|
|
99b710a57d | 13 years ago |
|
|
f55e0b847c | 13 years ago |
|
|
62d7e357f4 | 13 years ago |
|
|
12bd8e8827 | 13 years ago |
|
|
3a31d49309 | 13 years ago |
|
|
815c0e795d | 13 years ago |
|
|
02526e814d | 13 years ago |
|
|
7cebb6ea79 | 13 years ago |
|
|
36fe86a1f5 | 13 years ago |
|
|
1793a674ff | 13 years ago |
|
|
58d5b00883 | 13 years ago |
|
|
e774bf4be4 | 13 years ago |
|
|
c606b329b8 | 13 years ago |
|
|
767f8a8e9b | 13 years ago |
|
|
708a4d3820 | 13 years ago |
|
|
3d22fa59fe | 13 years ago |
|
|
18b5790a7c | 13 years ago |
|
|
d1e4fd9a5a | 13 years ago |
|
|
363793d9cb | 13 years ago |
34 changed files with 8522 additions and 7 deletions
@ -0,0 +1,62 @@ |
|||||
|
// <copyright file="SquareMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Complex |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for square matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SquareMatrix : Matrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Number of rows or columns.
|
||||
|
/// </summary>
|
||||
|
protected readonly int Order; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SquareMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If the matrix is not square.
|
||||
|
/// </exception>
|
||||
|
protected SquareMatrix(MatrixStorage<Complex> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
if (storage.RowCount != storage.ColumnCount) |
||||
|
{ |
||||
|
throw new ArgumentException(Resources.ArgumentMatrixSquare); |
||||
|
} |
||||
|
|
||||
|
Order = storage.RowCount; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,767 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Complex |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
using Generic; |
||||
|
using MathNet.Numerics.Distributions; |
||||
|
using MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A Symmetric Matrix class with dense storage.
|
||||
|
/// </summary>
|
||||
|
/// <remarks> The underlying storage is a one dimensional array in column-major order.
|
||||
|
/// The Upper Triangle is stored(it is equal to the Lower Triangle) </remarks>
|
||||
|
[Serializable] |
||||
|
public class SymmetricDenseMatrix : SymmetricMatrix |
||||
|
{ |
||||
|
readonly DenseColumnMajorSymmetricMatrixStorage<Complex> _storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
readonly Complex[] _data; |
||||
|
|
||||
|
internal SymmetricDenseMatrix(DenseColumnMajorSymmetricMatrixStorage<Complex> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
_storage = storage; |
||||
|
_data = _storage.Data; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class. This matrix is square with a given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The order of the matrix.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<Complex>(order)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class with all entries set to a particular value.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">
|
||||
|
/// The order of the matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">The value which we assign to each element of the matrix.</param>
|
||||
|
public SymmetricDenseMatrix(int order, Complex value) |
||||
|
: this(order) |
||||
|
{ |
||||
|
for (var i = 0; i < _data.Length; i++) |
||||
|
{ |
||||
|
_data[i] = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a one dimensional array. This constructor
|
||||
|
/// will reference the one dimensional array and not copy it.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix.</param>
|
||||
|
/// <param name="array">
|
||||
|
/// 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
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> does not represent a packed array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order, Complex[] array) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<Complex>(order, array)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a 2D array. This constructor
|
||||
|
/// will allocate a completely new memory block for storing the symmetric dense matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">The 2D array to create this matrix from.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a square array.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a symmetric array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(Complex[,] 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]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class, copying
|
||||
|
/// the values from the given matrix. Matrix must be Symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The matrix to copy.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a square matrix.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a symmetric matrix.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
public Complex[] Data |
||||
|
{ |
||||
|
get { return _data; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <c>SymmetricDenseMatrix</c> for the given number of rows and columns.
|
||||
|
/// If rows and columns are not equal, returns a <c>DenseMatrix</c> instead.
|
||||
|
/// </summary>
|
||||
|
/// <param name="numberOfRows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="numberOfColumns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
||||
|
/// <returns>
|
||||
|
/// A <c>DenseMatrix</c> or <c>SymmetricDenseMatrix</c> with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
/// /// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="numberOfRows"/> is not equal to <paramref name="numberOfColumns"/>.
|
||||
|
/// Symmetric arrays are always square
|
||||
|
/// </exception>
|
||||
|
public override Matrix<Complex> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
||||
|
{ |
||||
|
if (numberOfRows != numberOfColumns || fullyMutable) |
||||
|
{ |
||||
|
return new DenseMatrix(numberOfRows, numberOfColumns); |
||||
|
} |
||||
|
|
||||
|
return new SymmetricDenseMatrix(numberOfRows); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <see cref="Vector{T}"/> with a the given dimension.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">The size of the vector.</param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="Vector{T}"/> with the given dimension.
|
||||
|
/// </returns>
|
||||
|
public override Vector<Complex> CreateVector(int size, bool fullyMutable = false) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
#region Static constructors for special matrices.
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a square <see cref="SymmetricDenseMatrix"/> with all zero's except for ones on the diagonal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">the size of the square matrix.</param>
|
||||
|
/// <returns>A symmetric dense identity matrix.</returns>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public static SymmetricDenseMatrix Identity(int order) |
||||
|
{ |
||||
|
var m = new SymmetricDenseMatrix(order); |
||||
|
for (var i = 0; i < order; i++) |
||||
|
{ |
||||
|
m.At(i, i, Complex.One); |
||||
|
} |
||||
|
|
||||
|
return m; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <param name="result">The matrix to store the result of add</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
protected override void DoAdd(Matrix<Complex> other, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the subtraction.</param>
|
||||
|
protected override void DoSubtract(Matrix<Complex> other, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">The scalar to multiply the matrix with.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Complex scalar, Matrix<Complex> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoMultiply(scalar, result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The vector to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Vector<Complex> rightSide, Vector<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Matrix<Complex> other, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with transpose of another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoTransposeAndMultiply(Matrix<Complex> other, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">The result of the negation.</param>
|
||||
|
protected override void DoNegate(Matrix<Complex> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
|
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoNegate(result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<Complex> other, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise divide this one by.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise division.</param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<Complex> other, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the trace of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The trace of this matrix</returns>
|
||||
|
public override Complex Trace() |
||||
|
{ |
||||
|
// Matrix is always square.
|
||||
|
var sum = Complex.Zero; |
||||
|
for (var i = 0; i < RowCount; i++) |
||||
|
{ |
||||
|
sum += At(i, i); |
||||
|
} |
||||
|
|
||||
|
return sum; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<Complex> 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] = distribution.Sample(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<Complex> 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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to add.</param>
|
||||
|
/// <param name="rightSide">The right matrix to add.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a <strong>Matrix</strong> containing the same values of <paramref name="rightSide"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to get the values from.</param>
|
||||
|
/// <returns>A matrix containing a the same values as <paramref name="rightSide"/>.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator +(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to subtract.</param>
|
||||
|
/// <param name="rightSide">The right matrix to subtract.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negates each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to negate.</param>
|
||||
|
/// <returns>A matrix containing the negated values.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator -(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Negate(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(SymmetricDenseMatrix leftSide, Complex rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(Complex leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Multiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies two matrices.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The right matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the dimensions of <paramref name="leftSide"/> or <paramref name="rightSide"/> don't conform.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> and a Vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The vector to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(SymmetricDenseMatrix leftSide, DenseVector rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a Vector and a <strong>Matrix</strong>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The vector to multiply.</param>
|
||||
|
/// <param name="rightSide">The matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(DenseVector leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)rightSide.LeftMultiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator %(SymmetricDenseMatrix leftSide, Complex rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Modulus(rightSide); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,657 @@ |
|||||
|
// <copyright file="SymmetricMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Complex |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
using Generic; |
||||
|
using Distributions; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SymmetricMatrix : SquareMatrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
protected SymmetricMatrix(MatrixStorage<Complex> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a value indicating whether the array is symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">
|
||||
|
/// The array to check for symmetry.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// True is array is symmetric, false if not symmetric.
|
||||
|
/// </returns>
|
||||
|
public static bool CheckIfSymmetric(Complex[,] 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether this matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
public override sealed bool IsSymmetric |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the transpose of this matrix. The transpose is equal and this method returns a reference to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The transpose of this matrix.
|
||||
|
/// </returns>
|
||||
|
public override sealed Matrix<Complex> Transpose() |
||||
|
{ |
||||
|
return this.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the conjugate transpose of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The conjugate transpose of this matrix.</returns>
|
||||
|
public override Matrix<Complex> ConjugateTranspose() |
||||
|
{ |
||||
|
var ret = CreateMatrix(ColumnCount, RowCount); |
||||
|
for (var row = 0; row < RowCount; row++) |
||||
|
{ |
||||
|
for (var column = row; column < ColumnCount; column++) |
||||
|
{ |
||||
|
ret.At(row, column, At(column, row).Conjugate()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<Complex> Add(Matrix<Complex> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoAdd(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to add to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the addition.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoAdd(Matrix<Complex> other, Matrix<Complex> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <returns>The result of the subtraction.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<Complex> Subtract(Matrix<Complex> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoSubtract(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to subtract to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of subtraction.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoSubtract(Matrix<Complex> other, Matrix<Complex> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">
|
||||
|
/// The scalar to multiply the matrix with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoMultiply(Complex scalar, Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Matrix<Complex> other, Matrix<Complex> result) |
||||
|
{ |
||||
|
DoMultiply(other, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">
|
||||
|
/// The vector to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Vector<Complex> rightSide, Vector<Complex> result) |
||||
|
{ |
||||
|
DoMultiply(rightSide, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the negation.
|
||||
|
/// </param>
|
||||
|
protected override void DoNegate(Matrix<Complex> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise multiplication of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<Complex> PointwiseMultiply(Matrix<Complex> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other, "other"); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseMultiply(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise multiply with this one.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<Complex> other, Matrix<Complex> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise subtract this one by.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise division of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<Complex> PointwiseDivide(Matrix<Complex> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseDivide(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise divide this one by.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise division.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<Complex> other, Matrix<Complex> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the modulus for each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="divisor">
|
||||
|
/// The divisor to use.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// Matrix to store the results in.
|
||||
|
/// </param>
|
||||
|
protected override void DoModulus(Complex divisor, Matrix<Complex> result) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<Complex> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<Complex> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given column at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The index of where to insert the column.</param>
|
||||
|
/// <param name="column">The column to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column "/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is < zero or > the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> != the number of rows.</exception>
|
||||
|
public override Matrix<Complex> InsertColumn(int columnIndex, Vector<Complex> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a column is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, Complex[] column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, Vector<Complex> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given row at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The index of where to insert the row.</param>
|
||||
|
/// <param name="row">The row to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is < zero or > the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> != the number of columns.</exception>
|
||||
|
public override Matrix<Complex> InsertRow(int rowIndex, Vector<Complex> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a row is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, Vector<Complex> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, Complex[] row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
// <copyright file="SquareMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Complex32 |
||||
|
{ |
||||
|
using System; |
||||
|
using Numerics; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for square matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SquareMatrix : Matrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Number of rows or columns.
|
||||
|
/// </summary>
|
||||
|
protected readonly int Order; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SquareMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If the matrix is not square.
|
||||
|
/// </exception>
|
||||
|
protected SquareMatrix(MatrixStorage<Complex32> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
if (storage.RowCount != storage.ColumnCount) |
||||
|
{ |
||||
|
throw new ArgumentException(Resources.ArgumentMatrixSquare); |
||||
|
} |
||||
|
|
||||
|
Order = storage.RowCount; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,767 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
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; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A Symmetric Matrix class with dense storage.
|
||||
|
/// </summary>
|
||||
|
/// <remarks> The underlying storage is a one dimensional array in column-major order.
|
||||
|
/// The Upper Triangle is stored(it is equal to the Lower Triangle) </remarks>
|
||||
|
[Serializable] |
||||
|
public class SymmetricDenseMatrix : SymmetricMatrix |
||||
|
{ |
||||
|
readonly DenseColumnMajorSymmetricMatrixStorage<Complex32> _storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
readonly Complex32[] _data; |
||||
|
|
||||
|
internal SymmetricDenseMatrix(DenseColumnMajorSymmetricMatrixStorage<Complex32> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
_storage = storage; |
||||
|
_data = _storage.Data; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class. This matrix is square with a given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The order of the matrix.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<Complex32>(order)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class with all entries set to a particular value.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">
|
||||
|
/// The order of the matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">The value which we assign to each element of the matrix.</param>
|
||||
|
public SymmetricDenseMatrix(int order, Complex32 value) |
||||
|
: this(order) |
||||
|
{ |
||||
|
for (var i = 0; i < _data.Length; i++) |
||||
|
{ |
||||
|
_data[i] = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a one dimensional array. This constructor
|
||||
|
/// will reference the one dimensional array and not copy it.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix.</param>
|
||||
|
/// <param name="array">
|
||||
|
/// 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
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> does not represent a packed array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order, Complex32[] array) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<Complex32>(order, array)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a 2D array. This constructor
|
||||
|
/// will allocate a completely new memory block for storing the symmetric dense matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">The 2D array to create this matrix from.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a square array.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a symmetric array.
|
||||
|
/// </exception>
|
||||
|
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]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class, copying
|
||||
|
/// the values from the given matrix. Matrix must be Symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The matrix to copy.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a square matrix.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a symmetric matrix.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
public Complex32[] Data |
||||
|
{ |
||||
|
get { return _data; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <c>SymmetricDenseMatrix</c> for the given number of rows and columns.
|
||||
|
/// If rows and columns are not equal, returns a <c>DenseMatrix</c> instead.
|
||||
|
/// </summary>
|
||||
|
/// <param name="numberOfRows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="numberOfColumns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
||||
|
/// <returns>
|
||||
|
/// A <c>DenseMatrix</c> or <c>SymmetricDenseMatrix</c> with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
/// /// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="numberOfRows"/> is not equal to <paramref name="numberOfColumns"/>.
|
||||
|
/// Symmetric arrays are always square
|
||||
|
/// </exception>
|
||||
|
public override Matrix<Complex32> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
||||
|
{ |
||||
|
if (numberOfRows != numberOfColumns || fullyMutable) |
||||
|
{ |
||||
|
return new DenseMatrix(numberOfRows, numberOfColumns); |
||||
|
} |
||||
|
|
||||
|
return new SymmetricDenseMatrix(numberOfRows); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <see cref="Vector{T}"/> with a the given dimension.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">The size of the vector.</param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="Vector{T}"/> with the given dimension.
|
||||
|
/// </returns>
|
||||
|
public override Vector<Complex32> CreateVector(int size, bool fullyMutable = false) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
#region Static constructors for special matrices.
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a square <see cref="SymmetricDenseMatrix"/> with all zero's except for ones on the diagonal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">the size of the square matrix.</param>
|
||||
|
/// <returns>A symmetric dense identity matrix.</returns>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public static SymmetricDenseMatrix Identity(int order) |
||||
|
{ |
||||
|
var m = new SymmetricDenseMatrix(order); |
||||
|
for (var i = 0; i < order; i++) |
||||
|
{ |
||||
|
m.At(i, i, Complex32.One); |
||||
|
} |
||||
|
|
||||
|
return m; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <param name="result">The matrix to store the result of add</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
protected override void DoAdd(Matrix<Complex32> other, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the subtraction.</param>
|
||||
|
protected override void DoSubtract(Matrix<Complex32> other, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">The scalar to multiply the matrix with.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Complex32 scalar, Matrix<Complex32> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoMultiply(scalar, result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The vector to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Vector<Complex32> rightSide, Vector<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Matrix<Complex32> other, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with transpose of another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoTransposeAndMultiply(Matrix<Complex32> other, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">The result of the negation.</param>
|
||||
|
protected override void DoNegate(Matrix<Complex32> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
|
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoNegate(result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<Complex32> other, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise divide this one by.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise division.</param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<Complex32> other, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex32> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex32> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex32> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<Complex32> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the trace of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The trace of this matrix</returns>
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<Complex32> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<Complex32> 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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to add.</param>
|
||||
|
/// <param name="rightSide">The right matrix to add.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a <strong>Matrix</strong> containing the same values of <paramref name="rightSide"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to get the values from.</param>
|
||||
|
/// <returns>A matrix containing a the same values as <paramref name="rightSide"/>.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator +(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to subtract.</param>
|
||||
|
/// <param name="rightSide">The right matrix to subtract.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negates each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to negate.</param>
|
||||
|
/// <returns>A matrix containing the negated values.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator -(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Negate(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(SymmetricDenseMatrix leftSide, Complex32 rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(Complex32 leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Multiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies two matrices.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The right matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the dimensions of <paramref name="leftSide"/> or <paramref name="rightSide"/> don't conform.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> and a Vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The vector to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(SymmetricDenseMatrix leftSide, DenseVector rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a Vector and a <strong>Matrix</strong>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The vector to multiply.</param>
|
||||
|
/// <param name="rightSide">The matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(DenseVector leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)rightSide.LeftMultiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator %(SymmetricDenseMatrix leftSide, Complex32 rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Modulus(rightSide); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,657 @@ |
|||||
|
// <copyright file="SymmetricMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Complex32 |
||||
|
{ |
||||
|
using System; |
||||
|
using Numerics; |
||||
|
using Generic; |
||||
|
using Distributions; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SymmetricMatrix : SquareMatrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
protected SymmetricMatrix(MatrixStorage<Complex32> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a value indicating whether the array is symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">
|
||||
|
/// The array to check for symmetry.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// True is array is symmetric, false if not symmetric.
|
||||
|
/// </returns>
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether this matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
public override sealed bool IsSymmetric |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the transpose of this matrix. The transpose is equal and this method returns a reference to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The transpose of this matrix.
|
||||
|
/// </returns>
|
||||
|
public override sealed Matrix<Complex32> Transpose() |
||||
|
{ |
||||
|
return this.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the conjugate transpose of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The conjugate transpose of this matrix.</returns>
|
||||
|
public override Matrix<Complex32> ConjugateTranspose() |
||||
|
{ |
||||
|
var ret = CreateMatrix(ColumnCount, RowCount); |
||||
|
for (var row = 0; row < RowCount; row++) |
||||
|
{ |
||||
|
for (var column = row; column < ColumnCount; column++) |
||||
|
{ |
||||
|
ret.At(row, column, At(column, row).Conjugate()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<Complex32> Add(Matrix<Complex32> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex32> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoAdd(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to add to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the addition.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoAdd(Matrix<Complex32> other, Matrix<Complex32> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <returns>The result of the subtraction.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<Complex32> Subtract(Matrix<Complex32> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex32> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoSubtract(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to subtract to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of subtraction.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoSubtract(Matrix<Complex32> other, Matrix<Complex32> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">
|
||||
|
/// The scalar to multiply the matrix with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoMultiply(Complex32 scalar, Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Matrix<Complex32> other, Matrix<Complex32> result) |
||||
|
{ |
||||
|
DoMultiply(other, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">
|
||||
|
/// The vector to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Vector<Complex32> rightSide, Vector<Complex32> result) |
||||
|
{ |
||||
|
DoMultiply(rightSide, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the negation.
|
||||
|
/// </param>
|
||||
|
protected override void DoNegate(Matrix<Complex32> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise multiplication of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<Complex32> PointwiseMultiply(Matrix<Complex32> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other, "other"); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex32> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseMultiply(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise multiply with this one.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<Complex32> other, Matrix<Complex32> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise subtract this one by.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise division of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<Complex32> PointwiseDivide(Matrix<Complex32> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<Complex32> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseDivide(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise divide this one by.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise division.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<Complex32> other, Matrix<Complex32> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the modulus for each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="divisor">
|
||||
|
/// The divisor to use.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// Matrix to store the results in.
|
||||
|
/// </param>
|
||||
|
protected override void DoModulus(Complex32 divisor, Matrix<Complex32> result) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<Complex32> 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())); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<Complex32> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given column at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The index of where to insert the column.</param>
|
||||
|
/// <param name="column">The column to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column "/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is < zero or > the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> != the number of rows.</exception>
|
||||
|
public override Matrix<Complex32> InsertColumn(int columnIndex, Vector<Complex32> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a column is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, Complex32[] column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, Vector<Complex32> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given row at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The index of where to insert the row.</param>
|
||||
|
/// <param name="row">The row to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is < zero or > the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> != the number of columns.</exception>
|
||||
|
public override Matrix<Complex32> InsertRow(int rowIndex, Vector<Complex32> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a row is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, Vector<Complex32> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, Complex32[] row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
// <copyright file="SquareMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Double |
||||
|
{ |
||||
|
using System; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for square matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SquareMatrix : Matrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Number of rows or columns.
|
||||
|
/// </summary>
|
||||
|
protected readonly int Order; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SquareMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If the matrix is not square.
|
||||
|
/// </exception>
|
||||
|
protected SquareMatrix(MatrixStorage<double> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
if (storage.RowCount != storage.ColumnCount) |
||||
|
{ |
||||
|
throw new ArgumentException(Resources.ArgumentMatrixSquare); |
||||
|
} |
||||
|
|
||||
|
Order = storage.RowCount; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,794 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Double |
||||
|
{ |
||||
|
using System; |
||||
|
using Generic; |
||||
|
using MathNet.Numerics.Distributions; |
||||
|
using MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static; |
||||
|
using MathNet.Numerics.Threading; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A Symmetric Matrix class with dense storage.
|
||||
|
/// </summary>
|
||||
|
/// <remarks> The underlying storage is a one dimensional array in column-major order.
|
||||
|
/// The Upper Triangle is stored(it is equal to the Lower Triangle) </remarks>
|
||||
|
[Serializable] |
||||
|
public class SymmetricDenseMatrix : SymmetricMatrix |
||||
|
{ |
||||
|
readonly DenseColumnMajorSymmetricMatrixStorage<double> _storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
readonly double[] _data; |
||||
|
|
||||
|
internal SymmetricDenseMatrix(DenseColumnMajorSymmetricMatrixStorage<double> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
_storage = storage; |
||||
|
_data = _storage.Data; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class. This matrix is square with a given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The order of the matrix.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<double>(order)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class with all entries set to a particular value.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">
|
||||
|
/// The order of the matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">The value which we assign to each element of the matrix.</param>
|
||||
|
public SymmetricDenseMatrix(int order, double value) |
||||
|
: this(order) |
||||
|
{ |
||||
|
for (var i = 0; i < _data.Length; i++) |
||||
|
{ |
||||
|
_data[i] = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a one dimensional array. This constructor
|
||||
|
/// will reference the one dimensional array and not copy it.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix.</param>
|
||||
|
/// <param name="array">
|
||||
|
/// 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
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> does not represent a packed array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order, double[] array) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<double>(order, array)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a 2D array. This constructor
|
||||
|
/// will allocate a completely new memory block for storing the symmetric dense matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">The 2D array to create this matrix from.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a square array.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a symmetric array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(double[,] 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]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class, copying
|
||||
|
/// the values from the given matrix. Matrix must be Symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The matrix to copy.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a square matrix.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a symmetric matrix.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
public double[] Data |
||||
|
{ |
||||
|
get { return _data; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <c>SymmetricDenseMatrix</c> for the given number of rows and columns.
|
||||
|
/// If rows and columns are not equal, returns a <c>DenseMatrix</c> instead.
|
||||
|
/// </summary>
|
||||
|
/// <param name="numberOfRows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="numberOfColumns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
||||
|
/// <returns>
|
||||
|
/// A <c>DenseMatrix</c> or <c>SymmetricDenseMatrix</c> with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
/// /// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="numberOfRows"/> is not equal to <paramref name="numberOfColumns"/>.
|
||||
|
/// Symmetric arrays are always square
|
||||
|
/// </exception>
|
||||
|
public override Matrix<double> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
||||
|
{ |
||||
|
if (numberOfRows != numberOfColumns || fullyMutable) |
||||
|
{ |
||||
|
return new DenseMatrix(numberOfRows, numberOfColumns); |
||||
|
} |
||||
|
|
||||
|
return new SymmetricDenseMatrix(numberOfRows); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <see cref="Vector{T}"/> with a the given dimension.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">The size of the vector.</param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="Vector{T}"/> with the given dimension.
|
||||
|
/// </returns>
|
||||
|
public override Vector<double> CreateVector(int size, bool fullyMutable = false) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
#region Static constructors for special matrices.
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a square <see cref="SymmetricDenseMatrix"/> with all zero's except for ones on the diagonal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">the size of the square matrix.</param>
|
||||
|
/// <returns>A symmetric dense identity matrix.</returns>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public static SymmetricDenseMatrix Identity(int order) |
||||
|
{ |
||||
|
var m = new SymmetricDenseMatrix(order); |
||||
|
for (var i = 0; i < order; i++) |
||||
|
{ |
||||
|
m.At(i, i, 1.0); |
||||
|
} |
||||
|
|
||||
|
return m; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <param name="result">The matrix to store the result of add</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
protected override void DoAdd(Matrix<double> other, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the subtraction.</param>
|
||||
|
protected override void DoSubtract(Matrix<double> other, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">The scalar to multiply the matrix with.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(double scalar, Matrix<double> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoMultiply(scalar, result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The vector to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Vector<double> rightSide, Vector<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Matrix<double> other, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with transpose of another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoTransposeAndMultiply(Matrix<double> other, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">The result of the negation.</param>
|
||||
|
protected override void DoNegate(Matrix<double> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
|
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoNegate(result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<double> other, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise divide this one by.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise division.</param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<double> other, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<double> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<double> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<double> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<double> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the modulus for each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="divisor">The divisor to use.</param>
|
||||
|
/// <param name="result">Matrix to store the results in.</param>
|
||||
|
protected override void DoModulus(double divisor, Matrix<double> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
|
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoModulus(divisor, result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (!ReferenceEquals(this, result)) |
||||
|
{ |
||||
|
CopyTo(result); |
||||
|
} |
||||
|
|
||||
|
CommonParallel.For( |
||||
|
0, |
||||
|
_data.Length, |
||||
|
index => denseResult._data[index] %= divisor); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the trace of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The trace of this matrix</returns>
|
||||
|
public override double Trace() |
||||
|
{ |
||||
|
// Matrix is always square.
|
||||
|
var sum = 0.0; |
||||
|
for (var i = 0; i < RowCount; i++) |
||||
|
{ |
||||
|
sum += At(i, i); |
||||
|
} |
||||
|
|
||||
|
return sum; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<double> 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] = distribution.Sample(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<double> 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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to add.</param>
|
||||
|
/// <param name="rightSide">The right matrix to add.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a <strong>Matrix</strong> containing the same values of <paramref name="rightSide"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to get the values from.</param>
|
||||
|
/// <returns>A matrix containing a the same values as <paramref name="rightSide"/>.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator +(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to subtract.</param>
|
||||
|
/// <param name="rightSide">The right matrix to subtract.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negates each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to negate.</param>
|
||||
|
/// <returns>A matrix containing the negated values.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator -(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Negate(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(SymmetricDenseMatrix leftSide, double rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(double leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Multiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies two matrices.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The right matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the dimensions of <paramref name="leftSide"/> or <paramref name="rightSide"/> don't conform.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> and a Vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The vector to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(SymmetricDenseMatrix leftSide, DenseVector rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a Vector and a <strong>Matrix</strong>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The vector to multiply.</param>
|
||||
|
/// <param name="rightSide">The matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(DenseVector leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)rightSide.LeftMultiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator %(SymmetricDenseMatrix leftSide, double rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Modulus(rightSide); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,653 @@ |
|||||
|
// <copyright file="SymmetricMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Double |
||||
|
{ |
||||
|
using System; |
||||
|
using Generic; |
||||
|
using Distributions; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SymmetricMatrix : SquareMatrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
protected SymmetricMatrix(MatrixStorage<double> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a value indicating whether the array is symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">
|
||||
|
/// The array to check for symmetry.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// True is array is symmetric, false if not symmetric.
|
||||
|
/// </returns>
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether this matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
public override sealed bool IsSymmetric |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the transpose of this matrix. The transpose is equal and this method returns a reference to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The transpose of this matrix.
|
||||
|
/// </returns>
|
||||
|
public override sealed Matrix<double> Transpose() |
||||
|
{ |
||||
|
return this.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<double> Add(Matrix<double> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<double> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoAdd(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to add to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the addition.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoAdd(Matrix<double> other, Matrix<double> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <returns>The result of the subtraction.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<double> Subtract(Matrix<double> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<double> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoSubtract(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to subtract to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of subtraction.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoSubtract(Matrix<double> other, Matrix<double> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">
|
||||
|
/// The scalar to multiply the matrix with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoMultiply(double scalar, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Matrix<double> other, Matrix<double> result) |
||||
|
{ |
||||
|
DoMultiply(other, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">
|
||||
|
/// The vector to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Vector<double> rightSide, Vector<double> result) |
||||
|
{ |
||||
|
DoMultiply(rightSide, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the negation.
|
||||
|
/// </param>
|
||||
|
protected override void DoNegate(Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise multiplication of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<double> PointwiseMultiply(Matrix<double> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other, "other"); |
||||
|
} |
||||
|
|
||||
|
Matrix<double> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseMultiply(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise multiply with this one.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<double> other, Matrix<double> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise subtract this one by.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise division of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<double> PointwiseDivide(Matrix<double> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<double> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseDivide(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise divide this one by.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise division.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<double> other, Matrix<double> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the modulus for each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="divisor">
|
||||
|
/// The divisor to use.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// Matrix to store the results in.
|
||||
|
/// </param>
|
||||
|
protected override void DoModulus(double divisor, Matrix<double> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<double> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<double> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given column at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The index of where to insert the column.</param>
|
||||
|
/// <param name="column">The column to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column "/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is < zero or > the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> != the number of rows.</exception>
|
||||
|
public override Matrix<double> InsertColumn(int columnIndex, Vector<double> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a column is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, double[] column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, Vector<double> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given row at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The index of where to insert the row.</param>
|
||||
|
/// <param name="row">The row to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is < zero or > the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> != the number of columns.</exception>
|
||||
|
public override Matrix<double> InsertRow(int rowIndex, Vector<double> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a row is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, Vector<double> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, double[] row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
// <copyright file="SquareMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Single |
||||
|
{ |
||||
|
using System; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for square matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SquareMatrix : Matrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Number of rows or columns.
|
||||
|
/// </summary>
|
||||
|
protected readonly int Order; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="MathNet.Numerics.LinearAlgebra.Double.SquareMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If the matrix is not square.
|
||||
|
/// </exception>
|
||||
|
protected SquareMatrix(MatrixStorage<float> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
if (storage.RowCount != storage.ColumnCount) |
||||
|
{ |
||||
|
throw new ArgumentException(Resources.ArgumentMatrixSquare); |
||||
|
} |
||||
|
|
||||
|
Order = storage.RowCount; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,794 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Single |
||||
|
{ |
||||
|
using System; |
||||
|
using Generic; |
||||
|
using MathNet.Numerics.Distributions; |
||||
|
using MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static; |
||||
|
using MathNet.Numerics.Threading; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A Symmetric Matrix class with dense storage.
|
||||
|
/// </summary>
|
||||
|
/// <remarks> The underlying storage is a one dimensional array in column-major order.
|
||||
|
/// The Upper Triangle is stored(it is equal to the Lower Triangle) </remarks>
|
||||
|
[Serializable] |
||||
|
public class SymmetricDenseMatrix : SymmetricMatrix |
||||
|
{ |
||||
|
readonly DenseColumnMajorSymmetricMatrixStorage<float> _storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
readonly float[] _data; |
||||
|
|
||||
|
internal SymmetricDenseMatrix(DenseColumnMajorSymmetricMatrixStorage<float> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
_storage = storage; |
||||
|
_data = _storage.Data; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class. This matrix is square with a given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The order of the matrix.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<float>(order)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class with all entries set to a particular value.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">
|
||||
|
/// The order of the matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">The value which we assign to each element of the matrix.</param>
|
||||
|
public SymmetricDenseMatrix(int order, float value) |
||||
|
: this(order) |
||||
|
{ |
||||
|
for (var i = 0; i < _data.Length; i++) |
||||
|
{ |
||||
|
_data[i] = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a one dimensional array. This constructor
|
||||
|
/// will reference the one dimensional array and not copy it.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix.</param>
|
||||
|
/// <param name="array">
|
||||
|
/// 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
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> does not represent a packed array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(int order, float[] array) |
||||
|
: this(new DenseColumnMajorSymmetricMatrixStorage<float>(order, array)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class from a 2D array. This constructor
|
||||
|
/// will allocate a completely new memory block for storing the symmetric dense matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">The 2D array to create this matrix from.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a square array.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="array"/> is not a symmetric array.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(float[,] 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]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricDenseMatrix"/> class, copying
|
||||
|
/// the values from the given matrix. Matrix must be Symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The matrix to copy.</param>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a square matrix.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="matrix"/> is not a symmetric matrix.
|
||||
|
/// </exception>
|
||||
|
public SymmetricDenseMatrix(Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the matrix's data.
|
||||
|
/// </summary>
|
||||
|
/// <value>The matrix's data.</value>
|
||||
|
public float[] Data |
||||
|
{ |
||||
|
get { return _data; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <c>SymmetricDenseMatrix</c> for the given number of rows and columns.
|
||||
|
/// If rows and columns are not equal, returns a <c>DenseMatrix</c> instead.
|
||||
|
/// </summary>
|
||||
|
/// <param name="numberOfRows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="numberOfColumns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
||||
|
/// <returns>
|
||||
|
/// A <c>DenseMatrix</c> or <c>SymmetricDenseMatrix</c> with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
/// /// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="numberOfRows"/> is not equal to <paramref name="numberOfColumns"/>.
|
||||
|
/// Symmetric arrays are always square
|
||||
|
/// </exception>
|
||||
|
public override Matrix<float> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
||||
|
{ |
||||
|
if (numberOfRows != numberOfColumns || fullyMutable) |
||||
|
{ |
||||
|
return new DenseMatrix(numberOfRows, numberOfColumns); |
||||
|
} |
||||
|
|
||||
|
return new SymmetricDenseMatrix(numberOfRows); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a <see cref="Vector{T}"/> with a the given dimension.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">The size of the vector.</param>
|
||||
|
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="Vector{T}"/> with the given dimension.
|
||||
|
/// </returns>
|
||||
|
public override Vector<float> CreateVector(int size, bool fullyMutable = false) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
#region Static constructors for special matrices.
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a square <see cref="SymmetricDenseMatrix"/> with all zero's except for ones on the diagonal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">the size of the square matrix.</param>
|
||||
|
/// <returns>A symmetric dense identity matrix.</returns>
|
||||
|
/// <exception cref="ArgumentException">
|
||||
|
/// If <paramref name="order"/> is less than one.
|
||||
|
/// </exception>
|
||||
|
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
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <param name="result">The matrix to store the result of add</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
protected override void DoAdd(Matrix<float> other, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the subtraction.</param>
|
||||
|
protected override void DoSubtract(Matrix<float> other, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">The scalar to multiply the matrix with.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(float scalar, Matrix<float> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoMultiply(scalar, result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The vector to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Vector<float> rightSide, Vector<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoMultiply(Matrix<float> other, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies this matrix with transpose of another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to multiply with.</param>
|
||||
|
/// <param name="result">The result of the multiplication.</param>
|
||||
|
protected override void DoTransposeAndMultiply(Matrix<float> other, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">The result of the negation.</param>
|
||||
|
protected override void DoNegate(Matrix<float> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
|
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoNegate(result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<float> other, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise divide this one by.</param>
|
||||
|
/// <param name="result">The matrix to store the result of the pointwise division.</param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<float> other, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<float> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the lower triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The lower triangle of this matrix.</returns>
|
||||
|
public override Matrix<float> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<float> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a new matrix containing the upper triangle of this matrix. The new matrix
|
||||
|
/// does not contain the diagonal elements of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The upper triangle of this matrix.</returns>
|
||||
|
public override Matrix<float> 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the modulus for each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="divisor">The divisor to use.</param>
|
||||
|
/// <param name="result">Matrix to store the results in.</param>
|
||||
|
protected override void DoModulus(float divisor, Matrix<float> result) |
||||
|
{ |
||||
|
var denseResult = result as SymmetricDenseMatrix; |
||||
|
|
||||
|
if (denseResult == null) |
||||
|
{ |
||||
|
base.DoModulus(divisor, result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (!ReferenceEquals(this, result)) |
||||
|
{ |
||||
|
CopyTo(result); |
||||
|
} |
||||
|
|
||||
|
CommonParallel.For( |
||||
|
0, |
||||
|
_data.Length, |
||||
|
index => denseResult._data[index] %= divisor); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the trace of this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The trace of this matrix</returns>
|
||||
|
public override float Trace() |
||||
|
{ |
||||
|
// Matrix is always square.
|
||||
|
var sum = 0.0f; |
||||
|
for (var i = 0; i < RowCount; i++) |
||||
|
{ |
||||
|
sum += At(i, i); |
||||
|
} |
||||
|
|
||||
|
return sum; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<float> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a symmetric matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The symmetric matrix to populate.</param>
|
||||
|
/// <param name="distribution">Continuous Random Distribution to generate elements from.</param>
|
||||
|
protected override void DoRandom(Matrix<float> 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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to add.</param>
|
||||
|
/// <param name="rightSide">The right matrix to add.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a <strong>Matrix</strong> containing the same values of <paramref name="rightSide"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to get the values from.</param>
|
||||
|
/// <returns>A matrix containing a the same values as <paramref name="rightSide"/>.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator +(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts two matrices together and returns the results.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to subtract.</param>
|
||||
|
/// <param name="rightSide">The right matrix to subtract.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negates each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">The matrix to negate.</param>
|
||||
|
/// <returns>A matrix containing the negated values.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator -(SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Negate(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(SymmetricDenseMatrix leftSide, float rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator *(float leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)rightSide.Multiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies two matrices.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This operator will allocate new memory for the result. It will
|
||||
|
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
|
||||
|
/// is denser.</remarks>
|
||||
|
/// <param name="leftSide">The left matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The right matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the dimensions of <paramref name="leftSide"/> or <paramref name="rightSide"/> don't conform.</exception>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> and a Vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The vector to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(SymmetricDenseMatrix leftSide, DenseVector rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)leftSide.Multiply(rightSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a Vector and a <strong>Matrix</strong>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The vector to multiply.</param>
|
||||
|
/// <param name="rightSide">The matrix to multiply.</param>
|
||||
|
/// <returns>The result of multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
|
||||
|
public static DenseVector operator *(DenseVector leftSide, SymmetricDenseMatrix rightSide) |
||||
|
{ |
||||
|
if (rightSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("rightSide"); |
||||
|
} |
||||
|
|
||||
|
return (DenseVector)rightSide.LeftMultiply(leftSide); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
|
||||
|
/// </summary>
|
||||
|
/// <param name="leftSide">The matrix to multiply.</param>
|
||||
|
/// <param name="rightSide">The constant to multiply the matrix by.</param>
|
||||
|
/// <returns>The result of the multiplication.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
|
||||
|
public static SymmetricDenseMatrix operator %(SymmetricDenseMatrix leftSide, float rightSide) |
||||
|
{ |
||||
|
if (leftSide == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("leftSide"); |
||||
|
} |
||||
|
|
||||
|
return (SymmetricDenseMatrix)leftSide.Modulus(rightSide); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,653 @@ |
|||||
|
// <copyright file="SymmetricMatrix.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Single |
||||
|
{ |
||||
|
using System; |
||||
|
using Generic; |
||||
|
using Distributions; |
||||
|
using Properties; |
||||
|
using Storage; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
[Serializable] |
||||
|
public abstract class SymmetricMatrix : SquareMatrix |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SymmetricMatrix"/> class.
|
||||
|
/// </summary>
|
||||
|
protected SymmetricMatrix(MatrixStorage<float> storage) |
||||
|
: base(storage) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a value indicating whether the array is symmetric.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">
|
||||
|
/// The array to check for symmetry.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// True is array is symmetric, false if not symmetric.
|
||||
|
/// </returns>
|
||||
|
public static bool CheckIfSymmetric(float[,] 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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether this matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
public override sealed bool IsSymmetric |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the transpose of this matrix. The transpose is equal and this method returns a reference to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The transpose of this matrix.
|
||||
|
/// </returns>
|
||||
|
public override sealed Matrix<float> Transpose() |
||||
|
{ |
||||
|
return this.Clone(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to add to this matrix.</param>
|
||||
|
/// <returns>The result of the addition.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<float> Add(Matrix<float> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<float> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoAdd(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds another matrix to this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to add to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the addition.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoAdd(Matrix<float> other, Matrix<float> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to subtract.</param>
|
||||
|
/// <returns>The result of the subtraction.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
|
||||
|
public override Matrix<float> Subtract(Matrix<float> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<float> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
DoSubtract(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Subtracts another matrix from this matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to subtract to this matrix.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of subtraction.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentNullException">
|
||||
|
/// If the other matrix is <see langword="null"/>.
|
||||
|
/// </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// If the two matrices don't have the same dimensions.
|
||||
|
/// </exception>
|
||||
|
protected override void DoSubtract(Matrix<float> other, Matrix<float> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies each element of the matrix by a scalar and places results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="scalar">
|
||||
|
/// The scalar to multiply the matrix with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoMultiply(float scalar, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Matrix<float> other, Matrix<float> result) |
||||
|
{ |
||||
|
DoMultiply(other, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Multiplies the transpose of this matrix with a vector and places the results into the result vector.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rightSide">
|
||||
|
/// The vector to multiply with.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the multiplication.
|
||||
|
/// </param>
|
||||
|
protected override sealed void DoTransposeThisAndMultiply(Vector<float> rightSide, Vector<float> result) |
||||
|
{ |
||||
|
DoMultiply(rightSide, result); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Negate each element of this matrix and place the results into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="result">
|
||||
|
/// The result of the negation.
|
||||
|
/// </param>
|
||||
|
protected override void DoNegate(Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise multiply with this one.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise multiplication of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<float> PointwiseMultiply(Matrix<float> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other, "other"); |
||||
|
} |
||||
|
|
||||
|
Matrix<float> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseMultiply(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise multiply with this one.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise multiplication.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseMultiply(Matrix<float> other, Matrix<float> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The matrix to pointwise subtract this one by.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
|
||||
|
/// <returns>A new matrix that is the pointwise division of this matrix and <paramref name="other"/>.</returns>
|
||||
|
public override Matrix<float> PointwiseDivide(Matrix<float> other) |
||||
|
{ |
||||
|
if (other == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("other"); |
||||
|
} |
||||
|
|
||||
|
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) |
||||
|
{ |
||||
|
throw DimensionsDontMatch<ArgumentException>(this, other); |
||||
|
} |
||||
|
|
||||
|
Matrix<float> result; |
||||
|
if (other is SymmetricMatrix) |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
result = CreateMatrix(RowCount, ColumnCount, true); |
||||
|
} |
||||
|
|
||||
|
PointwiseDivide(other, result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">
|
||||
|
/// The matrix to pointwise divide this one by.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// The matrix to store the result of the pointwise division.
|
||||
|
/// </param>
|
||||
|
protected override void DoPointwiseDivide(Matrix<float> other, Matrix<float> 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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Computes the modulus for each element of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="divisor">
|
||||
|
/// The divisor to use.
|
||||
|
/// </param>
|
||||
|
/// <param name="result">
|
||||
|
/// Matrix to store the results in.
|
||||
|
/// </param>
|
||||
|
protected override void DoModulus(float divisor, Matrix<float> 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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<float> 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())); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Populates a matrix with random elements.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">
|
||||
|
/// The matrix to populate.
|
||||
|
/// </param>
|
||||
|
/// <param name="distribution">
|
||||
|
/// Continuous Random Distribution to generate elements from.
|
||||
|
/// </param>
|
||||
|
protected override void DoRandom(Matrix<float> 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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given column at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The index of where to insert the column.</param>
|
||||
|
/// <param name="column">The column to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column "/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is < zero or > the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> != the number of rows.</exception>
|
||||
|
public override Matrix<float> InsertColumn(int columnIndex, Vector<float> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a column is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, float[] column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified column. The changes retain the symmetry of the matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="columnIndex">The column to copy the values to.</param>
|
||||
|
/// <param name="column">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="column"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="columnIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of columns.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="column"/> does not
|
||||
|
/// equal the number of rows of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetColumn(int columnIndex, Vector<float> column) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a column is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new matrix and inserts the given row at the given index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The index of where to insert the row.</param>
|
||||
|
/// <param name="row">The row to insert.</param>
|
||||
|
/// <returns>A new matrix with the inserted column.</returns>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />. </exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is < zero or > the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> != the number of columns.</exception>
|
||||
|
public override Matrix<float> InsertRow(int rowIndex, Vector<float> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Inserting a row is not supported on a symmetric matrix. Symmetric matrices are square"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given Vector to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The vector to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, Vector<float> row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the values of the given array to the specified row.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rowIndex">The row to copy the values to.</param>
|
||||
|
/// <param name="row">The array to copy the values from.</param>
|
||||
|
/// <exception cref="ArgumentNullException">If <paramref name="row"/> is <see langword="null" />.</exception>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="rowIndex"/> is less than zero,
|
||||
|
/// or greater than or equal to the number of rows.</exception>
|
||||
|
/// <exception cref="ArgumentException">If the size of <paramref name="row"/> does not
|
||||
|
/// equal the number of columns of this <strong>Matrix</strong>.</exception>
|
||||
|
public override void SetRow(int rowIndex, float[] row) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Setting a row is not supported on a symmetric matrix. It will violate symmetry"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,84 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Storage |
||||
|
{ |
||||
|
using MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static; |
||||
|
using MathNet.Numerics.Properties; |
||||
|
|
||||
|
public class DenseColumnMajorSymmetricMatrixStorage<T> : SymmetricMatrixStorage<T> |
||||
|
where T : struct, IEquatable<T>, IFormattable |
||||
|
{ |
||||
|
// [ruegg] public fields are OK here
|
||||
|
|
||||
|
public readonly T[] Data; |
||||
|
|
||||
|
public readonly PackedStorageIndexerUpper Indexer; |
||||
|
|
||||
|
internal DenseColumnMajorSymmetricMatrixStorage(int order) |
||||
|
: base(order) |
||||
|
{ |
||||
|
Indexer = new PackedStorageIndexerUpper(order); |
||||
|
Data = new T[Indexer.DataLength]; |
||||
|
} |
||||
|
|
||||
|
internal DenseColumnMajorSymmetricMatrixStorage(int order, T[] data) |
||||
|
: base(order) |
||||
|
{ |
||||
|
if (data == null) |
||||
|
{ |
||||
|
throw new ArgumentNullException("data"); |
||||
|
} |
||||
|
|
||||
|
Indexer = new PackedStorageIndexerUpper(order); |
||||
|
|
||||
|
if (data.Length != Indexer.DataLength) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, Indexer.DataLength)); |
||||
|
} |
||||
|
|
||||
|
Data = data; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the requested element without range checking.
|
||||
|
/// </summary>
|
||||
|
/// <param name="row">
|
||||
|
/// The row of the element.
|
||||
|
/// </param>
|
||||
|
/// <param name="column">
|
||||
|
/// The column of the element.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The requested element.
|
||||
|
/// </returns>
|
||||
|
/// <remarks>Not range-checked.</remarks>
|
||||
|
public override T At(int row, int column) |
||||
|
{ |
||||
|
var r = Math.Min(row, column); |
||||
|
var c = Math.Max(row, column); |
||||
|
return Data[Indexer.Of(r, c)]; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the element without range checking.
|
||||
|
/// </summary>
|
||||
|
/// <param name="row"> The row of the element. </param>
|
||||
|
/// <param name="column"> The column of the element. </param>
|
||||
|
/// <param name="value"> The value to set the element to. </param>
|
||||
|
/// <remarks>WARNING: This method is not thread safe. Use "lock" with it and be sure to avoid deadlocks.</remarks>
|
||||
|
public override void At(int row, int column, T value) |
||||
|
{ |
||||
|
if (row > column) |
||||
|
{ |
||||
|
throw new IndexOutOfRangeException("Setting an element in the strictly lower triangle of a symmetric matrix is disabled to avoid errors"); |
||||
|
} |
||||
|
|
||||
|
Data[Indexer.Of(row, column)] = value; |
||||
|
} |
||||
|
|
||||
|
public override void Clear() |
||||
|
{ |
||||
|
Array.Clear(Data, 0, Data.Length); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
namespace MathNet.Numerics.LinearAlgebra.Storage.Indexers |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Abstract class that defines common features for all storage schemes.
|
||||
|
/// </summary>
|
||||
|
public interface IStorageIndexer |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Retrieves the index of the requested element without parameter checking.
|
||||
|
/// </summary><param name="row">
|
||||
|
/// The row of the element.
|
||||
|
/// </param><param name="column">
|
||||
|
/// The column of the element.
|
||||
|
/// </param><returns>
|
||||
|
/// The requested index.
|
||||
|
/// </returns>
|
||||
|
int Of(int row, int column); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the index of the requested diagonal element without parameter checking.
|
||||
|
/// </summary><param name="row">
|
||||
|
/// The row=column of the diagonal element.
|
||||
|
/// </param><returns>
|
||||
|
/// The requested index.
|
||||
|
/// </returns>
|
||||
|
int OfDiagonal(int row); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
namespace MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static |
||||
|
{ |
||||
|
using System; |
||||
|
using Properties; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A class for managing indexing when using Packed Storage, which is a column-major packing scheme for dense Symmetric, Hermitian or Triangular square matrices.
|
||||
|
/// </summary>
|
||||
|
public abstract class PackedStorageIndexer : StaticStorageIndexer |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Number of rows or columns.
|
||||
|
/// </summary>
|
||||
|
protected readonly int Order; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Length of the stored data.
|
||||
|
/// </summary>
|
||||
|
private readonly int _dataLength; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PackedStorageIndexer"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">
|
||||
|
/// The order of the matrix.
|
||||
|
/// </param>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException"><c></c> is out of range.</exception>
|
||||
|
protected PackedStorageIndexer(int order) |
||||
|
{ |
||||
|
if (order <= 0) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException(Resources.MatrixRowsOrColumnsMustBePositive); |
||||
|
} |
||||
|
|
||||
|
Order = order; |
||||
|
_dataLength = order * (order + 1) / 2; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the length of the stored data.
|
||||
|
/// </summary>
|
||||
|
public override int DataLength |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _dataLength; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,88 @@ |
|||||
|
namespace MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static |
||||
|
{ |
||||
|
using System; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A class for managing indexes when using Packed Storage, which is a column-major packing scheme for Symmetric, Hermitian or Triangular square matrices.
|
||||
|
/// This variation provides indexes for storing the upper triangle of a matrix (row less than or equal to column).
|
||||
|
/// </summary>
|
||||
|
public class PackedStorageIndexerUpper : PackedStorageIndexer |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PackedStorageIndexerUpper"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">
|
||||
|
/// The order of the matrix.
|
||||
|
/// </param>
|
||||
|
internal PackedStorageIndexerUpper(int order) |
||||
|
: base(order) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the index of the given element.
|
||||
|
/// </summary>
|
||||
|
/// <param name = "row">
|
||||
|
/// The row of the element.
|
||||
|
/// </param>
|
||||
|
/// <param name = "column">
|
||||
|
/// The column of the element.
|
||||
|
/// </param>
|
||||
|
/// <remarks>
|
||||
|
/// This method is parameter checked. <see cref = "Of" /> and <see cref = "OfDiagonal" /> to get values without parameter checking.
|
||||
|
/// </remarks>
|
||||
|
public override int this[int row, int column] |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
if (row < 0 || row >= Order) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException("row"); |
||||
|
} |
||||
|
|
||||
|
if (column < 0 || column >= Order) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException("column"); |
||||
|
} |
||||
|
|
||||
|
if (row > column) |
||||
|
{ |
||||
|
throw new ArgumentException("Row must be less than or equal to column"); |
||||
|
} |
||||
|
|
||||
|
return this.Of(row, column); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the index of the requested element without parameter checking. Row must be less than or equal to column.
|
||||
|
/// </summary>
|
||||
|
/// <param name="row">
|
||||
|
/// The row of the element.
|
||||
|
/// </param>
|
||||
|
/// <param name="column">
|
||||
|
/// The column of the element.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The requested index.
|
||||
|
/// </returns>
|
||||
|
public override int Of(int row, int column) |
||||
|
{ |
||||
|
return row + ((column * (column + 1)) / 2); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the index of the requested diagonal element without parameter checking.
|
||||
|
/// </summary>
|
||||
|
/// <param name="row">
|
||||
|
/// The row=column of the diagonal element.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The requested index.
|
||||
|
/// </returns>
|
||||
|
public override int OfDiagonal(int row) |
||||
|
{ |
||||
|
return (row * (row + 3)) / 2; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
namespace MathNet.Numerics.LinearAlgebra.Storage.Indexers.Static |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Classes that contain indexing information of a static storage scheme.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// A static storage scheme is always the same and only depends on the size of the matrix.
|
||||
|
/// </remarks>
|
||||
|
public abstract class StaticStorageIndexer : IStorageIndexer |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the index of the given element.
|
||||
|
/// </summary>
|
||||
|
/// <param name = "row">
|
||||
|
/// The row of the element.
|
||||
|
/// </param>
|
||||
|
/// <param name = "column">
|
||||
|
/// The column of the element.
|
||||
|
/// </param>
|
||||
|
/// <remarks>
|
||||
|
/// This method is parameter checked. <see cref = "IStorageIndexer.Of" /> and <see cref = "IStorageIndexer.OfDiagonal" /> to get values without parameter checking.
|
||||
|
/// </remarks>
|
||||
|
public abstract int this[int row, int column] |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the length of the stored data.
|
||||
|
/// </summary>
|
||||
|
public abstract int DataLength |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the index of the requested element without parameter checking.
|
||||
|
/// </summary><param name="row">
|
||||
|
/// The row of the element.
|
||||
|
/// </param><param name="column">
|
||||
|
/// The column of the element.
|
||||
|
/// </param><returns>
|
||||
|
/// The requested index.
|
||||
|
/// </returns>
|
||||
|
public abstract int Of(int row, int column); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the index of the requested diagonal element without parameter checking.
|
||||
|
/// </summary><param name="row">
|
||||
|
/// The row=column of the diagonal element.
|
||||
|
/// </param><returns>
|
||||
|
/// The requested index.
|
||||
|
/// </returns>
|
||||
|
public abstract int OfDiagonal(int row); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace MathNet.Numerics.LinearAlgebra.Storage |
||||
|
{ |
||||
|
using MathNet.Numerics.Properties; |
||||
|
|
||||
|
public abstract class SymmetricMatrixStorage<T> : MatrixStorage<T> |
||||
|
where T : struct, IEquatable<T>, IFormattable |
||||
|
{ |
||||
|
// [ruegg] public fields are OK here
|
||||
|
|
||||
|
protected SymmetricMatrixStorage(int order) |
||||
|
: base(order, order) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override bool IsFullyMutable |
||||
|
{ |
||||
|
get { return false; } |
||||
|
} |
||||
|
|
||||
|
public override bool IsMutable(int row, int column) |
||||
|
{ |
||||
|
return row <= column; |
||||
|
} |
||||
|
|
||||
|
public override void Clear() |
||||
|
{ |
||||
|
for (var i = 0; i < RowCount; i++) |
||||
|
{ |
||||
|
for (var j = i; j < ColumnCount; j++) |
||||
|
{ |
||||
|
At(i, j, default(T)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void Clear(int rowIndex, int rowCount, int columnIndex, int columnCount) |
||||
|
{ |
||||
|
for (var i = rowIndex; i < rowIndex + rowCount; i++) |
||||
|
{ |
||||
|
for (var j = Math.Max(columnIndex, i); j < columnIndex + columnCount; j++) |
||||
|
{ |
||||
|
At(i, j, default(T)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <remarks>Parameters assumed to be validated already.</remarks>
|
||||
|
public override void CopyTo(MatrixStorage<T> target, bool skipClearing = false) |
||||
|
{ |
||||
|
for (int j = 0; j < ColumnCount; j++) |
||||
|
{ |
||||
|
for (int i = 0; i <= j; i++) |
||||
|
{ |
||||
|
target.At(i, j, At(i, j)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,217 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
using MathNet.Numerics.LinearAlgebra.Complex; |
||||
|
|
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Symmetric Dense matrix tests.
|
||||
|
/// </summary>
|
||||
|
public class SymmetricDenseMatrixTests : SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Creates a matrix for the given number of rows and columns.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="columns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(int rows, int columns) |
||||
|
{ |
||||
|
return new DenseMatrix(rows, columns); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a matrix from a 2D array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The 2D array to create this matrix from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given values.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(Complex[,] data) |
||||
|
{ |
||||
|
if (SymmetricMatrix.CheckIfSymmetric(data)) |
||||
|
{ |
||||
|
return new SymmetricDenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
return new DenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector of the given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">
|
||||
|
/// The size of the vector to create.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(int size) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector from an array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The array to create this vector from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(Complex[] data) |
||||
|
{ |
||||
|
return new DenseVector(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom1DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(3, new[] { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(0.0, 1), new Complex(3.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(3, new[] { new Complex(-1.1, 1), new Complex(2.0, 1), new Complex(1.1, 1), new Complex(3.0, 1), new Complex(0.0, 1), new Complex(6.6, 1) }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(4, new[] { new Complex(1.1, 1), new Complex(2.0, 1), new Complex(5.0, 1), new Complex(-3.0, 1), new Complex(-6.0, 1), new Complex(8.0, 1), new Complex(4.4, 1), new Complex(7.0, 1), new Complex(9.0, 1), new Complex(10.0, 1) }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(4, new[] { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(5.0, 1), new Complex(0.0, 1), new Complex(0.0, 1), new Complex(0.0, 1), new Complex(4.0, 1), new Complex(7.0, 1), new Complex(0.0, 1), new Complex(10.0, 1) }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(3, new[] { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(2.0, 1), new Complex(3.0, 1), new Complex(0.0, 1), new Complex(3.0, 1) }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(4, new [] { new Complex(0, 1), new Complex(1, 1), new Complex(2, 1), new Complex(3, 1), new Complex(4, 1), new Complex(5, 1), new Complex(6, 1), new Complex(7, 1), new Complex(8, 1), new Complex(9, 1) }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from array is a reference.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom1DArrayIsReference() |
||||
|
{ |
||||
|
var data = new Complex[] { new Complex(1, 1), new Complex(1, 1), new Complex(1, 1), new Complex(1, 1), new Complex(1, 1), new Complex(1, 1) }; |
||||
|
var matrix = new SymmetricDenseMatrix(3, data); |
||||
|
matrix[0, 0] = new Complex(10.0, 2); |
||||
|
Assert.AreEqual(new Complex(10.0, 2), data[0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom2DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(new[,] { { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(3.0, 1) }, { new Complex(2.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) }, { new Complex(3.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) } }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(new[,] { { new Complex(-1.1, 1), new Complex(2.0, 1), new Complex(3.0, 1) }, { new Complex(2.0, 1), new Complex(1.1, 1), new Complex(0.0, 1) }, { new Complex(3.0, 1), new Complex(0.0, 1), new Complex(6.6, 1) } }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(new[,] { { new Complex(1.1, 1), new Complex(2.0, 1), new Complex(-3.0, 1), new Complex(4.4, 1) }, { new Complex(2.0, 1), new Complex(5.0, 1), new Complex(-6.0, 1), new Complex(7.0, 1) }, { new Complex(-3.0, 1), new Complex(-6.0, 1), new Complex(8.0, 1), new Complex(9.0, 1) }, { new Complex(4.4, 1), new Complex(7.0, 1), new Complex(9.0, 1), new Complex(10.0, 1) } }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(new[,] { { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(0.0, 1), new Complex(4.0, 1) }, { new Complex(2.0, 1), new Complex(5.0, 1), new Complex(0.0, 1), new Complex(7.0, 1) }, { new Complex(0.0, 1), new Complex(0.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) }, { new Complex(4.0, 1), new Complex(7.0, 1), new Complex(0.0, 1), new Complex(10.0, 1) } }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(new[,] { { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(3.0, 1) }, { new Complex(2.0, 1), new Complex(2.0, 1), new Complex(0.0, 1) }, { new Complex(3.0, 1), new Complex(0.0, 1), new Complex(3.0, 1) } }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(new [,] { { new Complex(0, 1), new Complex(1, 1), new Complex(3, 1), new Complex(6, 1) }, { new Complex(1, 1), new Complex(2, 1), new Complex(4, 1), new Complex(7, 1) }, { new Complex(3, 1), new Complex(4, 1), new Complex(5, 1), new Complex(8, 1) }, { new Complex(6, 1), new Complex(7, 1), new Complex(8, 1), new Complex(9, 1) } }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from two-dimensional array is a copy.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom2DArrayIsCopy() |
||||
|
{ |
||||
|
var matrix = new DenseMatrix(TestData2D["Singular3x3"]); |
||||
|
matrix[0, 0] = new Complex(10.0, 2); |
||||
|
Assert.AreEqual(new Complex(1.0, 1), TestData2D["Singular3x3"][0, 0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix with uniform values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixWithUniformValues() |
||||
|
{ |
||||
|
var matrix = new SymmetricDenseMatrix(10, new Complex(10.0, 2)); |
||||
|
var value = new Complex(10.0, 2); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create an identity matrix.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateIdentity() |
||||
|
{ |
||||
|
var matrix = SymmetricDenseMatrix.Identity(5); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(i == j ? Complex.One : Complex.Zero, matrix[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity with wrong order throws <c>ArgumentOutOfRangeException</c>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix</param>
|
||||
|
[TestCase(0)] |
||||
|
[TestCase(-1)] |
||||
|
public void IdentityWithWrongOrderThrowsArgumentOutOfRangeException(int order) |
||||
|
{ |
||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => SymmetricDenseMatrix.Identity(order)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,192 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.Arithmetic.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex |
||||
|
{ |
||||
|
using System.Collections.Generic; |
||||
|
using LinearAlgebra.Complex; |
||||
|
using NUnit.Framework; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Setup test matrices.
|
||||
|
/// Singular and Square matrices are overridden here with symmetric ones so that calls to base methods work as intended.
|
||||
|
/// Additional NonSymmetric matrices are defined for some tests.
|
||||
|
/// </summary>
|
||||
|
[SetUp] |
||||
|
public override void SetupMatrices() |
||||
|
{ |
||||
|
TestData2D = new Dictionary<string, Complex[,]> |
||||
|
{ |
||||
|
{ "Singular3x3", new[,] { { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(3.0, 1) }, { new Complex(2.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) }, { new Complex(3.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) } } }, |
||||
|
{ "Square3x3", new[,] { { new Complex(-1.1, 1), new Complex(2.0, 1), new Complex(3.0, 1) }, { new Complex(2.0, 1), new Complex(1.1, 1), new Complex(0.0, 1) }, { new Complex(3.0, 1), new Complex(0.0, 1), new Complex(6.6, 1) } } }, |
||||
|
{ "Square4x4", new[,] { { new Complex(1.1, 1), new Complex(2.0, 1), new Complex(-3.0, 1), new Complex(4.4, 1) }, { new Complex(2.0, 1), new Complex(5.0, 1), new Complex(-6.0, 1), new Complex(7.0, 1) }, { new Complex(-3.0, 1), new Complex(-6.0, 1), new Complex(8.0, 1), new Complex(9.0, 1) }, { new Complex(4.4, 1), new Complex(7.0, 1), new Complex(9.0, 1), new Complex(10.0, 1) } } }, |
||||
|
{ "Singular4x4", new[,] { { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(0.0, 1), new Complex(4.0, 1) }, { new Complex(2.0, 1), new Complex(5.0, 1), new Complex(0.0, 1), new Complex(7.0, 1) }, { new Complex(0.0, 1), new Complex(0.0, 1), new Complex(0.0, 1), new Complex(0.0, 1) }, { new Complex(4.0, 1), new Complex(7.0, 1), new Complex(0.0, 1), new Complex(10.0, 1) } } }, |
||||
|
{ "Tall3x2", new[,] { { new Complex(-1.1, 1), new Complex(-2.2, 1) }, { new Complex(0.0, 1), new Complex(1.1, 1) }, { new Complex(-4.4, 1), new Complex(5.5, 1) } } }, |
||||
|
{ "Wide2x3", new[,] { { new Complex(-1.1, 1), new Complex(-2.2, 1), new Complex(-3.3, 1) }, { new Complex(0.0, 1), new Complex(1.1, 1), new Complex(2.2, 1) } } }, |
||||
|
{ "Symmetric3x3", new[,] { { new Complex(1.0, 1), new Complex(2.0, 1), new Complex(3.0, 1) }, { new Complex(2.0, 1), new Complex(2.0, 1), new Complex(0.0, 1) }, { new Complex(3.0, 1), new Complex(0.0, 1), new Complex(3.0, 1) } } }, |
||||
|
{ "NonSymmetric3x3", new[,] { { new Complex(-1.1, 1), new Complex(-2.2, 1), new Complex(-3.3, 1) }, { new Complex(0.0, 1), new Complex(1.1, 1), new Complex(2.2, 1) }, { new Complex(-4.4, 1), new Complex(5.5, 1), new Complex(6.6, 1) } } }, |
||||
|
{ "NonSymmetric4x4", new[,] { { new Complex(-1.1, 1), new Complex(-2.2, 1), new Complex(-3.3, 1), new Complex(-4.4, 1) }, { new Complex(0.0, 1), new Complex(1.1, 1), new Complex(2.2, 1), new Complex(3.3, 1) }, { new Complex(1.0, 1), new Complex(2.1, 1), new Complex(6.2, 1), new Complex(4.3, 1) }, { new Complex(-4.4, 1), new Complex(5.5, 1), new Complex(6.6, 1), new Complex(-7.7, 1) } } }, |
||||
|
{ "IndexTester4x4", new [,] { { new Complex(0, 1), new Complex(1, 1), new Complex(3, 1), new Complex(6, 1) }, { new Complex(1, 1), new Complex(2, 1), new Complex(4, 1), new Complex(7, 1) }, { new Complex(3, 1), new Complex(4, 1), new Complex(5, 1), new Complex(8, 1) }, { new Complex(6, 1), new Complex(7, 1), new Complex(8, 1), new Complex(9, 1) } } } |
||||
|
}; |
||||
|
|
||||
|
TestMatrices = new Dictionary<string, Matrix>(); |
||||
|
|
||||
|
foreach (var name in TestData2D.Keys) |
||||
|
{ |
||||
|
TestMatrices.Add(name, CreateMatrix(TestData2D[name])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can add a non-symmetric matrix to this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanAddNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Add(matrixB); |
||||
|
|
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] + matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can subtract a non-symmetric matrix from this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanSubtractNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Subtract(matrixB); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] - matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Frobenius norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeFrobeniusNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Infinity norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeInfinityNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L1 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL1Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L2 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL2Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,124 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
using MathNet.Numerics.LinearAlgebra.Complex; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests : MatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Can check if a matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public override void CanCheckIfMatrixIsSymmetric() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
Assert.IsTrue(matrix.IsSymmetric); |
||||
|
|
||||
|
matrix = TestMatrices["NonSymmetric3x3"]; |
||||
|
Assert.IsFalse(matrix.IsSymmetric); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can check if a [,] array is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCheckIfArrayIsSymmetric() |
||||
|
{ |
||||
|
Assert.IsTrue(SymmetricMatrix.CheckIfSymmetric(TestData2D["Square3x3"])); |
||||
|
Assert.IsFalse(SymmetricMatrix.CheckIfSymmetric(TestData2D["NonSymmetric3x3"])); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Test whether the index enumerator returns the correct values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanUseIndexedEnumerator() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Singular3x3"]; |
||||
|
var enumerator = matrix.IndexedEnumerator().GetEnumerator(); |
||||
|
enumerator.MoveNext(); |
||||
|
var item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(new Complex(1.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(new Complex(2.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(new Complex(3.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(new Complex(2.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(new Complex(0.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(new Complex(0.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(new Complex(3.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(new Complex(0.0, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(new Complex(0.0, 1), item.Item3); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,217 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Numerics; |
||||
|
|
||||
|
using MathNet.Numerics.LinearAlgebra.Complex32; |
||||
|
|
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Symmetric Dense matrix tests.
|
||||
|
/// </summary>
|
||||
|
public class SymmetricDenseMatrixTests : SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Creates a matrix for the given number of rows and columns.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="columns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(int rows, int columns) |
||||
|
{ |
||||
|
return new DenseMatrix(rows, columns); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a matrix from a 2D array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The 2D array to create this matrix from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given values.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(Complex32[,] data) |
||||
|
{ |
||||
|
if (SymmetricMatrix.CheckIfSymmetric(data)) |
||||
|
{ |
||||
|
return new SymmetricDenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
return new DenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector of the given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">
|
||||
|
/// The size of the vector to create.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(int size) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector from an array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The array to create this vector from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(Complex32[] data) |
||||
|
{ |
||||
|
return new DenseVector(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom1DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(3, new[] { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(0.0f, 1), new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(3, new[] { new Complex32(-1.1f, 1), new Complex32(2.0f, 1), new Complex32(1.1f, 1), new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(6.6f, 1) }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(4, new[] { new Complex32(1.1f, 1), new Complex32(2.0f, 1), new Complex32(5.0f, 1), new Complex32(-3.0f, 1), new Complex32(-6.0f, 1), new Complex32(8.0f, 1), new Complex32(4.4f, 1), new Complex32(7.0f, 1), new Complex32(9.0f, 1), new Complex32(10.0f, 1) }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(4, new[] { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(5.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1), new Complex32(4.0f, 1), new Complex32(7.0f, 1), new Complex32(0.0f, 1), new Complex32(10.0f, 1) }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(3, new[] { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(3.0f, 1) }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(4, new [] { new Complex32(0, 1), new Complex32(1, 1), new Complex32(2, 1), new Complex32(3, 1), new Complex32(4, 1), new Complex32(5, 1), new Complex32(6, 1), new Complex32(7, 1), new Complex32(8, 1), new Complex32(9, 1) }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from array is a reference.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom1DArrayIsReference() |
||||
|
{ |
||||
|
var data = new Complex32[] { new Complex32(1, 1), new Complex32(1, 1), new Complex32(1, 1), new Complex32(1, 1), new Complex32(1, 1), new Complex32(1, 1) }; |
||||
|
var matrix = new SymmetricDenseMatrix(3, data); |
||||
|
matrix[0, 0] = new Complex32(10.0f, 2); |
||||
|
Assert.AreEqual(new Complex32(10.0f, 2), data[0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom2DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(new[,] { { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) }, { new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) } }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(new[,] { { new Complex32(-1.1f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(1.1f, 1), new Complex32(0.0f, 1) }, { new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(6.6f, 1) } }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(new[,] { { new Complex32(1.1f, 1), new Complex32(2.0f, 1), new Complex32(-3.0f, 1), new Complex32(4.4f, 1) }, { new Complex32(2.0f, 1), new Complex32(5.0f, 1), new Complex32(-6.0f, 1), new Complex32(7.0f, 1) }, { new Complex32(-3.0f, 1), new Complex32(-6.0f, 1), new Complex32(8.0f, 1), new Complex32(9.0f, 1) }, { new Complex32(4.4f, 1), new Complex32(7.0f, 1), new Complex32(9.0f, 1), new Complex32(10.0f, 1) } }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(new[,] { { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(0.0f, 1), new Complex32(4.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(5.0f, 1), new Complex32(0.0f, 1), new Complex32(7.0f, 1) }, { new Complex32(0.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) }, { new Complex32(4.0f, 1), new Complex32(7.0f, 1), new Complex32(0.0f, 1), new Complex32(10.0f, 1) } }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(new[,] { { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(2.0f, 1), new Complex32(0.0f, 1) }, { new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(3.0f, 1) } }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(new [,] { { new Complex32(0, 1), new Complex32(1, 1), new Complex32(3, 1), new Complex32(6, 1) }, { new Complex32(1, 1), new Complex32(2, 1), new Complex32(4, 1), new Complex32(7, 1) }, { new Complex32(3, 1), new Complex32(4, 1), new Complex32(5, 1), new Complex32(8, 1) }, { new Complex32(6, 1), new Complex32(7, 1), new Complex32(8, 1), new Complex32(9, 1) } }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from two-dimensional array is a copy.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom2DArrayIsCopy() |
||||
|
{ |
||||
|
var matrix = new DenseMatrix(TestData2D["Singular3x3"]); |
||||
|
matrix[0, 0] = new Complex32(10.0f, 2); |
||||
|
Assert.AreEqual(new Complex32(1.0f, 1), TestData2D["Singular3x3"][0, 0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix with uniform values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixWithUniformValues() |
||||
|
{ |
||||
|
var matrix = new SymmetricDenseMatrix(10, new Complex32(10.0f, 2)); |
||||
|
var value = new Complex32(10.0f, 2); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create an identity matrix.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateIdentity() |
||||
|
{ |
||||
|
var matrix = SymmetricDenseMatrix.Identity(5); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(i == j ? Complex32.One : Complex32.Zero, matrix[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity with wrong order throws <c>ArgumentOutOfRangeException</c>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix</param>
|
||||
|
[TestCase(0)] |
||||
|
[TestCase(-1)] |
||||
|
public void IdentityWithWrongOrderThrowsArgumentOutOfRangeException(int order) |
||||
|
{ |
||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => SymmetricDenseMatrix.Identity(order)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,192 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.Arithmetic.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 |
||||
|
{ |
||||
|
using System.Collections.Generic; |
||||
|
using LinearAlgebra.Complex32; |
||||
|
using NUnit.Framework; |
||||
|
using Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Setup test matrices.
|
||||
|
/// Singular and Square matrices are overridden here with symmetric ones so that calls to base methods work as intended.
|
||||
|
/// Additional NonSymmetric matrices are defined for some tests.
|
||||
|
/// </summary>
|
||||
|
[SetUp] |
||||
|
public override void SetupMatrices() |
||||
|
{ |
||||
|
TestData2D = new Dictionary<string, Complex32[,]> |
||||
|
{ |
||||
|
{ "Singular3x3", new[,] { { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) }, { new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) } } }, |
||||
|
{ "Square3x3", new[,] { { new Complex32(-1.1f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(1.1f, 1), new Complex32(0.0f, 1) }, { new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(6.6f, 1) } } }, |
||||
|
{ "Square4x4", new[,] { { new Complex32(1.1f, 1), new Complex32(2.0f, 1), new Complex32(-3.0f, 1), new Complex32(4.4f, 1) }, { new Complex32(2.0f, 1), new Complex32(5.0f, 1), new Complex32(-6.0f, 1), new Complex32(7.0f, 1) }, { new Complex32(-3.0f, 1), new Complex32(-6.0f, 1), new Complex32(8.0f, 1), new Complex32(9.0f, 1) }, { new Complex32(4.4f, 1), new Complex32(7.0f, 1), new Complex32(9.0f, 1), new Complex32(10.0f, 1) } } }, |
||||
|
{ "Singular4x4", new[,] { { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(0.0f, 1), new Complex32(4.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(5.0f, 1), new Complex32(0.0f, 1), new Complex32(7.0f, 1) }, { new Complex32(0.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1), new Complex32(0.0f, 1) }, { new Complex32(4.0f, 1), new Complex32(7.0f, 1), new Complex32(0.0f, 1), new Complex32(10.0f, 1) } } }, |
||||
|
{ "Tall3x2", new[,] { { new Complex32(-1.1f, 1), new Complex32(-2.2f, 1) }, { new Complex32(0.0f, 1), new Complex32(1.1f, 1) }, { new Complex32(-4.4f, 1), new Complex32(5.5f, 1) } } }, |
||||
|
{ "Wide2x3", new[,] { { new Complex32(-1.1f, 1), new Complex32(-2.2f, 1), new Complex32(-3.3f, 1) }, { new Complex32(0.0f, 1), new Complex32(1.1f, 1), new Complex32(2.2f, 1) } } }, |
||||
|
{ "Symmetric3x3", new[,] { { new Complex32(1.0f, 1), new Complex32(2.0f, 1), new Complex32(3.0f, 1) }, { new Complex32(2.0f, 1), new Complex32(2.0f, 1), new Complex32(0.0f, 1) }, { new Complex32(3.0f, 1), new Complex32(0.0f, 1), new Complex32(3.0f, 1) } } }, |
||||
|
{ "NonSymmetric3x3", new[,] { { new Complex32(-1.1f, 1), new Complex32(-2.2f, 1), new Complex32(-3.3f, 1) }, { new Complex32(0.0f, 1), new Complex32(1.1f, 1), new Complex32(2.2f, 1) }, { new Complex32(-4.4f, 1), new Complex32(5.5f, 1), new Complex32(6.6f, 1) } } }, |
||||
|
{ "NonSymmetric4x4", new[,] { { new Complex32(-1.1f, 1), new Complex32(-2.2f, 1), new Complex32(-3.3f, 1), new Complex32(-4.4f, 1) }, { new Complex32(0.0f, 1), new Complex32(1.1f, 1), new Complex32(2.2f, 1), new Complex32(3.3f, 1) }, { new Complex32(1.0f, 1), new Complex32(2.1f, 1), new Complex32(6.2f, 1), new Complex32(4.3f, 1) }, { new Complex32(-4.4f, 1), new Complex32(5.5f, 1), new Complex32(6.6f, 1), new Complex32(-7.7f, 1) } } }, |
||||
|
{ "IndexTester4x4", new [,] { { new Complex32(0, 1), new Complex32(1, 1), new Complex32(3, 1), new Complex32(6, 1) }, { new Complex32(1, 1), new Complex32(2, 1), new Complex32(4, 1), new Complex32(7, 1) }, { new Complex32(3, 1), new Complex32(4, 1), new Complex32(5, 1), new Complex32(8, 1) }, { new Complex32(6, 1), new Complex32(7, 1), new Complex32(8, 1), new Complex32(9, 1) } } } |
||||
|
}; |
||||
|
|
||||
|
TestMatrices = new Dictionary<string, Matrix>(); |
||||
|
|
||||
|
foreach (var name in TestData2D.Keys) |
||||
|
{ |
||||
|
TestMatrices.Add(name, CreateMatrix(TestData2D[name])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can add a non-symmetric matrix to this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanAddNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Add(matrixB); |
||||
|
|
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] + matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can subtract a non-symmetric matrix from this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanSubtractNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Subtract(matrixB); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] - matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Frobenius norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeFrobeniusNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Infinity norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeInfinityNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L1 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL1Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L2 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL2Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 |
||||
|
{ |
||||
|
using MathNet.Numerics.LinearAlgebra.Complex32; |
||||
|
|
||||
|
using Numerics; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests : MatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Can check if a matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public override void CanCheckIfMatrixIsSymmetric() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
Assert.IsTrue(matrix.IsSymmetric); |
||||
|
|
||||
|
matrix = TestMatrices["NonSymmetric3x3"]; |
||||
|
Assert.IsFalse(matrix.IsSymmetric); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can check if a [,] array is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCheckIfArrayIsSymmetric() |
||||
|
{ |
||||
|
Assert.IsTrue(SymmetricMatrix.CheckIfSymmetric(TestData2D["Square3x3"])); |
||||
|
Assert.IsFalse(SymmetricMatrix.CheckIfSymmetric(TestData2D["NonSymmetric3x3"])); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Test whether the index enumerator returns the correct values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanUseIndexedEnumerator() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Singular3x3"]; |
||||
|
var enumerator = matrix.IndexedEnumerator().GetEnumerator(); |
||||
|
enumerator.MoveNext(); |
||||
|
var item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(1.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(2.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(3.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(2.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(0.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(0.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(3.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(0.0f, 1), item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(new Complex32(0.0f, 1), item.Item3); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,215 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
using MathNet.Numerics.LinearAlgebra.Double; |
||||
|
|
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Symmetric Dense matrix tests.
|
||||
|
/// </summary>
|
||||
|
public class SymmetricDenseMatrixTests : SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Creates a matrix for the given number of rows and columns.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="columns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(int rows, int columns) |
||||
|
{ |
||||
|
return new DenseMatrix(rows, columns); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a matrix from a 2D array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The 2D array to create this matrix from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given values.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(double[,] data) |
||||
|
{ |
||||
|
if (SymmetricMatrix.CheckIfSymmetric(data)) |
||||
|
{ |
||||
|
return new SymmetricDenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
return new DenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector of the given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">
|
||||
|
/// The size of the vector to create.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(int size) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector from an array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The array to create this vector from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(double[] data) |
||||
|
{ |
||||
|
return new DenseVector(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom1DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(3, new[] { 1.0, 2.0, 0.0, 3.0, 0.0, 0.0 }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(3, new[] { -1.1, 2.0, 1.1, 3.0, 0.0, 6.6 }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(4, new[] { 1.1, 2.0, 5.0, -3.0, -6.0, 8.0, 4.4, 7.0, 9.0, 10.0 }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(4, new[] { 1.0, 2.0, 5.0, 0.0, 0.0, 0.0, 4.0, 7.0, 0.0, 10.0 }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(3, new[] { 1.0, 2.0, 2.0, 3.0, 0.0, 3.0 }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(4, new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from array is a reference.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom1DArrayIsReference() |
||||
|
{ |
||||
|
var data = new double[] { 1, 1, 1, 1, 1, 1 }; |
||||
|
var matrix = new SymmetricDenseMatrix(3, data); |
||||
|
matrix[0, 0] = 10.0; |
||||
|
Assert.AreEqual(10.0, data[0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom2DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(new[,] { { 1.0, 2.0, 3.0 }, { 2.0, 0.0, 0.0 }, { 3.0, 0.0, 0.0 } }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(new[,] { { -1.1, 2.0, 3.0 }, { 2.0, 1.1, 0.0 }, { 3.0, 0.0, 6.6 } }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(new[,] { { 1.1, 2.0, -3.0, 4.4 }, { 2.0, 5.0, -6.0, 7.0 }, { -3.0, -6.0, 8.0, 9.0 }, { 4.4, 7.0, 9.0, 10.0 } }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(new[,] { { 1.0, 2.0, 0.0, 4.0 }, { 2.0, 5.0, 0.0, 7.0 }, { 0.0, 0.0, 0.0, 0.0 }, { 4.0, 7.0, 0.0, 10.0 } }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(new[,] { { 1.0, 2.0, 3.0 }, { 2.0, 2.0, 0.0 }, { 3.0, 0.0, 3.0 } }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(new double[,] { { 0, 1, 3, 6 }, { 1, 2, 4, 7 }, { 3, 4, 5, 8 }, { 6, 7, 8, 9 } }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from two-dimensional array is a copy.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom2DArrayIsCopy() |
||||
|
{ |
||||
|
var matrix = new DenseMatrix(TestData2D["Singular3x3"]); |
||||
|
matrix[0, 0] = 10.0; |
||||
|
Assert.AreEqual(1.0, TestData2D["Singular3x3"][0, 0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix with uniform values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixWithUniformValues() |
||||
|
{ |
||||
|
var matrix = new SymmetricDenseMatrix(10, 10.0); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], 10.0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create an identity matrix.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateIdentity() |
||||
|
{ |
||||
|
var matrix = SymmetricDenseMatrix.Identity(5); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(i == j ? 1.0 : 0.0, matrix[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity with wrong order throws <c>ArgumentOutOfRangeException</c>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix</param>
|
||||
|
[TestCase(0)] |
||||
|
[TestCase(-1)] |
||||
|
public void IdentityWithWrongOrderThrowsArgumentOutOfRangeException(int order) |
||||
|
{ |
||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => SymmetricDenseMatrix.Identity(order)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,191 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.Arithmetic.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double |
||||
|
{ |
||||
|
using System.Collections.Generic; |
||||
|
using LinearAlgebra.Double; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Setup test matrices.
|
||||
|
/// Singular and Square matrices are overridden here with symmetric ones so that calls to base methods work as intended.
|
||||
|
/// Additional NonSymmetric matrices are defined for some tests.
|
||||
|
/// </summary>
|
||||
|
[SetUp] |
||||
|
public override void SetupMatrices() |
||||
|
{ |
||||
|
TestData2D = new Dictionary<string, double[,]> |
||||
|
{ |
||||
|
{ "Singular3x3", new[,] { { 1.0, 2.0, 3.0 }, { 2.0, 0.0, 0.0 }, { 3.0, 0.0, 0.0 } } }, |
||||
|
{ "Square3x3", new[,] { { -1.1, 2.0, 3.0 }, { 2.0, 1.1, 0.0 }, { 3.0, 0.0, 6.6 } } }, |
||||
|
{ "Square4x4", new[,] { { 1.1, 2.0, -3.0, 4.4 }, { 2.0, 5.0, -6.0, 7.0 }, { -3.0, -6.0, 8.0, 9.0 }, { 4.4, 7.0, 9.0, 10.0 } } }, |
||||
|
{ "Singular4x4", new[,] { { 1.0, 2.0, 0.0, 4.0 }, { 2.0, 5.0, 0.0, 7.0 }, { 0.0, 0.0, 0.0, 0.0 }, { 4.0, 7.0, 0.0, 10.0 } } }, |
||||
|
{ "Tall3x2", new[,] { { -1.1, -2.2 }, { 0.0, 1.1 }, { -4.4, 5.5 } } }, |
||||
|
{ "Wide2x3", new[,] { { -1.1, -2.2, -3.3 }, { 0.0, 1.1, 2.2 } } }, |
||||
|
{ "Symmetric3x3", new[,] { { 1.0, 2.0, 3.0 }, { 2.0, 2.0, 0.0 }, { 3.0, 0.0, 3.0 } } }, |
||||
|
{ "NonSymmetric3x3", new[,] { { -1.1, -2.2, -3.3 }, { 0.0, 1.1, 2.2 }, { -4.4, 5.5, 6.6 } } }, |
||||
|
{ "NonSymmetric4x4", new[,] { { -1.1, -2.2, -3.3, -4.4 }, { 0.0, 1.1, 2.2, 3.3 }, { 1.0, 2.1, 6.2, 4.3 }, { -4.4, 5.5, 6.6, -7.7 } } }, |
||||
|
{ "IndexTester4x4", new double[,] { { 0, 1, 3, 6 }, { 1, 2, 4, 7 }, { 3, 4, 5, 8 }, { 6, 7, 8, 9 } } } |
||||
|
}; |
||||
|
|
||||
|
TestMatrices = new Dictionary<string, Matrix>(); |
||||
|
|
||||
|
foreach (var name in TestData2D.Keys) |
||||
|
{ |
||||
|
TestMatrices.Add(name, CreateMatrix(TestData2D[name])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can add a non-symmetric matrix to this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanAddNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Add(matrixB); |
||||
|
|
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] + matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can subtract a non-symmetric matrix from this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanSubtractNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Subtract(matrixB); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] - matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Frobenius norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeFrobeniusNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Infinity norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeInfinityNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L1 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL1Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L2 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL2Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,123 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double |
||||
|
{ |
||||
|
using MathNet.Numerics.LinearAlgebra.Double; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests : MatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Can check if a matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public override void CanCheckIfMatrixIsSymmetric() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
Assert.IsTrue(matrix.IsSymmetric); |
||||
|
|
||||
|
matrix = TestMatrices["NonSymmetric3x3"]; |
||||
|
Assert.IsFalse(matrix.IsSymmetric); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can check if a [,] array is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCheckIfArrayIsSymmetric() |
||||
|
{ |
||||
|
Assert.IsTrue(SymmetricMatrix.CheckIfSymmetric(TestData2D["Square3x3"])); |
||||
|
Assert.IsFalse(SymmetricMatrix.CheckIfSymmetric(TestData2D["NonSymmetric3x3"])); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Test whether the index enumerator returns the correct values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanUseIndexedEnumerator() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Singular3x3"]; |
||||
|
var enumerator = matrix.IndexedEnumerator().GetEnumerator(); |
||||
|
enumerator.MoveNext(); |
||||
|
var item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(1.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(2.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(3.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(2.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(3.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,215 @@ |
|||||
|
// <copyright file="SymmetricDenseMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
using MathNet.Numerics.LinearAlgebra.Single; |
||||
|
|
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Symmetric Dense matrix tests.
|
||||
|
/// </summary>
|
||||
|
public class SymmetricDenseMatrixTests : SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Creates a matrix for the given number of rows and columns.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rows">
|
||||
|
/// The number of rows.
|
||||
|
/// </param>
|
||||
|
/// <param name="columns">
|
||||
|
/// The number of columns.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given dimensions.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(int rows, int columns) |
||||
|
{ |
||||
|
return new DenseMatrix(rows, columns); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a matrix from a 2D array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The 2D array to create this matrix from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A matrix with the given values.
|
||||
|
/// </returns>
|
||||
|
protected override Matrix CreateMatrix(float[,] data) |
||||
|
{ |
||||
|
if (SymmetricMatrix.CheckIfSymmetric(data)) |
||||
|
{ |
||||
|
return new SymmetricDenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
return new DenseMatrix(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector of the given size.
|
||||
|
/// </summary>
|
||||
|
/// <param name="size">
|
||||
|
/// The size of the vector to create.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(int size) |
||||
|
{ |
||||
|
return new DenseVector(size); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a vector from an array.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">
|
||||
|
/// The array to create this vector from.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The new vector.
|
||||
|
/// </returns>
|
||||
|
protected override Vector CreateVector(float[] data) |
||||
|
{ |
||||
|
return new DenseVector(data); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom1DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(3, new[] { 1.0f, 2.0f, 0.0f, 3.0f, 0.0f, 0.0f }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(3, new[] { -1.1f, 2.0f, 1.1f, 3.0f, 0.0f, 6.6f }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(4, new[] { 1.1f, 2.0f, 5.0f, -3.0f, -6.0f, 8.0f, 4.4f, 7.0f, 9.0f, 10.0f }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(4, new[] { 1.0f, 2.0f, 5.0f, 0.0f, 0.0f, 0.0f, 4.0f, 7.0f, 0.0f, 10.0f }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(3, new[] { 1.0f, 2.0f, 2.0f, 3.0f, 0.0f, 3.0f }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(4, new [] { 0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from array is a reference.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom1DArrayIsReference() |
||||
|
{ |
||||
|
var data = new float[] { 1, 1, 1, 1, 1, 1 }; |
||||
|
var matrix = new SymmetricDenseMatrix(3, data); |
||||
|
matrix[0, 0] = 10.0f; |
||||
|
Assert.AreEqual(10.0f, data[0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix form array.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixFrom2DArray() |
||||
|
{ |
||||
|
var testData = new Dictionary<string, Matrix> |
||||
|
{ |
||||
|
{ "Singular3x3", new SymmetricDenseMatrix(new[,] { { 1.0f, 2.0f, 3.0f }, { 2.0f, 0.0f, 0.0f }, { 3.0f, 0.0f, 0.0f } }) }, |
||||
|
{ "Square3x3", new SymmetricDenseMatrix(new[,] { { -1.1f, 2.0f, 3.0f }, { 2.0f, 1.1f, 0.0f }, { 3.0f, 0.0f, 6.6f } }) }, |
||||
|
{ "Square4x4", new SymmetricDenseMatrix(new[,] { { 1.1f, 2.0f, -3.0f, 4.4f }, { 2.0f, 5.0f, -6.0f, 7.0f }, { -3.0f, -6.0f, 8.0f, 9.0f }, { 4.4f, 7.0f, 9.0f, 10.0f } }) }, |
||||
|
{ "Singular4x4", new SymmetricDenseMatrix(new[,] { { 1.0f, 2.0f, 0.0f, 4.0f }, { 2.0f, 5.0f, 0.0f, 7.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 4.0f, 7.0f, 0.0f, 10.0f } }) }, |
||||
|
{ "Symmetric3x3", new SymmetricDenseMatrix(new[,] { { 1.0f, 2.0f, 3.0f }, { 2.0f, 2.0f, 0.0f }, { 3.0f, 0.0f, 3.0f } }) }, |
||||
|
{ "IndexTester4x4", new SymmetricDenseMatrix(new [,] { { 0f, 1f, 3f, 6f }, { 1f, 2f, 4f, 7f }, { 3f, 4f, 5f, 8f }, { 6f, 7f, 8f, 9f } }) } |
||||
|
}; |
||||
|
|
||||
|
foreach (var name in testData.Keys) |
||||
|
{ |
||||
|
Assert.AreEqual(TestMatrices[name], testData[name]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Matrix from two-dimensional array is a copy.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void MatrixFrom2DArrayIsCopy() |
||||
|
{ |
||||
|
var matrix = new DenseMatrix(TestData2D["Singular3x3"]); |
||||
|
matrix[0, 0] = 10.0f; |
||||
|
Assert.AreEqual(1.0f, TestData2D["Singular3x3"][0, 0]); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create a matrix with uniform values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateMatrixWithUniformValues() |
||||
|
{ |
||||
|
var matrix = new SymmetricDenseMatrix(10, 10.0f); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], 10.0f); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can create an identity matrix.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCreateIdentity() |
||||
|
{ |
||||
|
var matrix = SymmetricDenseMatrix.Identity(5); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(i == j ? 1.0f : 0.0f, matrix[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity with wrong order throws <c>ArgumentOutOfRangeException</c>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="order">The size of the square matrix</param>
|
||||
|
[TestCase(0)] |
||||
|
[TestCase(-1)] |
||||
|
public void IdentityWithWrongOrderThrowsArgumentOutOfRangeException(int order) |
||||
|
{ |
||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => SymmetricDenseMatrix.Identity(order)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,191 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.Arithmetic.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single |
||||
|
{ |
||||
|
using System.Collections.Generic; |
||||
|
using LinearAlgebra.Single; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Setup test matrices.
|
||||
|
/// Singular and Square matrices are overridden here with symmetric ones so that calls to base methods work as intended.
|
||||
|
/// Additional NonSymmetric matrices are defined for some tests.
|
||||
|
/// </summary>
|
||||
|
[SetUp] |
||||
|
public override void SetupMatrices() |
||||
|
{ |
||||
|
TestData2D = new Dictionary<string, float[,]> |
||||
|
{ |
||||
|
{ "Singular3x3", new[,] { { 1.0f, 2.0f, 3.0f }, { 2.0f, 0.0f, 0.0f }, { 3.0f, 0.0f, 0.0f } } }, |
||||
|
{ "Square3x3", new[,] { { -1.1f, 2.0f, 3.0f }, { 2.0f, 1.1f, 0.0f }, { 3.0f, 0.0f, 6.6f } } }, |
||||
|
{ "Square4x4", new[,] { { 1.1f, 2.0f, -3.0f, 4.4f }, { 2.0f, 5.0f, -6.0f, 7.0f }, { -3.0f, -6.0f, 8.0f, 9.0f }, { 4.4f, 7.0f, 9.0f, 10.0f } } }, |
||||
|
{ "Singular4x4", new[,] { { 1.0f, 2.0f, 0.0f, 4.0f }, { 2.0f, 5.0f, 0.0f, 7.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 4.0f, 7.0f, 0.0f, 10.0f } } }, |
||||
|
{ "Tall3x2", new[,] { { -1.1f, -2.2f }, { 0.0f, 1.1f }, { -4.4f, 5.5f } } }, |
||||
|
{ "Wide2x3", new[,] { { -1.1f, -2.2f, -3.3f }, { 0.0f, 1.1f, 2.2f } } }, |
||||
|
{ "Symmetric3x3", new[,] { { 1.0f, 2.0f, 3.0f }, { 2.0f, 2.0f, 0.0f }, { 3.0f, 0.0f, 3.0f } } }, |
||||
|
{ "NonSymmetric3x3", new[,] { { -1.1f, -2.2f, -3.3f }, { 0.0f, 1.1f, 2.2f }, { -4.4f, 5.5f, 6.6f } } }, |
||||
|
{ "NonSymmetric4x4", new[,] { { -1.1f, -2.2f, -3.3f, -4.4f }, { 0.0f, 1.1f, 2.2f, 3.3f }, { 1.0f, 2.1f, 6.2f, 4.3f }, { -4.4f, 5.5f, 6.6f, -7.7f } } }, |
||||
|
{ "IndexTester4x4", new [,] { { 0f, 1f, 3f, 6f }, { 1f, 2f, 4f, 7f }, { 3f, 4f, 5f, 8f }, { 6f, 7f, 8f, 9f } } } |
||||
|
}; |
||||
|
|
||||
|
TestMatrices = new Dictionary<string, Matrix>(); |
||||
|
|
||||
|
foreach (var name in TestData2D.Keys) |
||||
|
{ |
||||
|
TestMatrices.Add(name, CreateMatrix(TestData2D[name])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can add a non-symmetric matrix to this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanAddNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Add(matrixB); |
||||
|
|
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] + matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can subtract a non-symmetric matrix from this symmetric matrix.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mtxA">Matrix A name.</param>
|
||||
|
/// <param name="mtxB">Matrix B name.</param>
|
||||
|
[Test, Sequential] |
||||
|
public void CanSubtractNonSymmetricMatrix([Values("Square3x3", "Square4x4")] string mtxA, [Values("NonSymmetric3x3", "NonSymmetric4x4")] string mtxB) |
||||
|
{ |
||||
|
var matrixA = TestMatrices[mtxA]; |
||||
|
var matrixB = TestMatrices[mtxB]; |
||||
|
|
||||
|
var matrix = matrixA.Clone(); |
||||
|
matrix = matrix.Subtract(matrixB); |
||||
|
for (var i = 0; i < matrix.RowCount; i++) |
||||
|
{ |
||||
|
for (var j = 0; j < matrix.ColumnCount; j++) |
||||
|
{ |
||||
|
Assert.AreEqual(matrix[i, j], matrixA[i, j] - matrixB[i, j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Frobenius norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeFrobeniusNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.FrobeniusNorm(), matrix.FrobeniusNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute Infinity norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeInfinityNorm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.InfinityNorm(), matrix.InfinityNorm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L1 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL1Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L1Norm(), matrix.L1Norm(), 14); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can compute L2 norm.
|
||||
|
/// </summary>
|
||||
|
public override void CanComputeL2Norm() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
var denseMatrix = new DenseMatrix(TestData2D["Square3x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Wide2x3"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Wide2x3"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
|
||||
|
matrix = TestMatrices["Tall3x2"]; |
||||
|
denseMatrix = new DenseMatrix(TestData2D["Tall3x2"]); |
||||
|
AssertHelpers.AlmostEqual(denseMatrix.L2Norm(), matrix.L2Norm(), 14); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,123 @@ |
|||||
|
// <copyright file="SymmetricMatrixTests.cs" company="Math.NET">
|
||||
|
// 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.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single |
||||
|
{ |
||||
|
using MathNet.Numerics.LinearAlgebra.Single; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Abstract class with the common set of matrix tests for symmetric matrices.
|
||||
|
/// </summary>
|
||||
|
public abstract partial class SymmetricMatrixTests : MatrixTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Can check if a matrix is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public override void CanCheckIfMatrixIsSymmetric() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Square3x3"]; |
||||
|
Assert.IsTrue(matrix.IsSymmetric); |
||||
|
|
||||
|
matrix = TestMatrices["NonSymmetric3x3"]; |
||||
|
Assert.IsFalse(matrix.IsSymmetric); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can check if a [,] array is symmetric.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanCheckIfArrayIsSymmetric() |
||||
|
{ |
||||
|
Assert.IsTrue(SymmetricMatrix.CheckIfSymmetric(TestData2D["Square3x3"])); |
||||
|
Assert.IsFalse(SymmetricMatrix.CheckIfSymmetric(TestData2D["NonSymmetric3x3"])); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Test whether the index enumerator returns the correct values.
|
||||
|
/// </summary>
|
||||
|
[Test] |
||||
|
public void CanUseIndexedEnumerator() |
||||
|
{ |
||||
|
var matrix = TestMatrices["Singular3x3"]; |
||||
|
var enumerator = matrix.IndexedEnumerator().GetEnumerator(); |
||||
|
enumerator.MoveNext(); |
||||
|
var item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(1.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(2.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(0, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(3.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(2.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(1, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(0, item.Item2); |
||||
|
Assert.AreEqual(3.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(1, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
|
||||
|
enumerator.MoveNext(); |
||||
|
item = enumerator.Current; |
||||
|
Assert.AreEqual(2, item.Item1); |
||||
|
Assert.AreEqual(2, item.Item2); |
||||
|
Assert.AreEqual(0.0, item.Item3); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue