diff --git a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs index d26e2265..3ef8717d 100644 --- a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs @@ -220,17 +220,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public override int GetHashCode() { var hashNum = Math.Min(_data.Length, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(_data[i].GetHashCode()); -#else - hash ^= BitConverter.DoubleToInt64Bits(_data[i].GetHashCode()); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + _data[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } #region Elementary operations diff --git a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs index 857dc40b..600c3b0e 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs @@ -623,17 +623,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex { var values = _storage.Values; var hashNum = Math.Min(_storage.ValueCount, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(values[i].Magnitude); -#else - hash ^= BitConverter.DoubleToInt64Bits(values[i].Magnitude); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + values[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs index 298111f5..44b9573e 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs @@ -220,17 +220,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public override int GetHashCode() { var hashNum = Math.Min(_data.Length, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(_data[i].GetHashCode()); -#else - hash ^= BitConverter.DoubleToInt64Bits(_data[i].GetHashCode()); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + _data[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } #region Elementary operations diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs index be25719a..bb5448b5 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs @@ -623,17 +623,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 { var values = _storage.Values; var hashNum = Math.Min(_storage.ValueCount, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(values[i].Magnitude); -#else - hash ^= BitConverter.DoubleToInt64Bits(values[i].Magnitude); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + values[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } /// diff --git a/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs index b3b6bbe8..eefc3637 100644 --- a/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs @@ -219,17 +219,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double public override int GetHashCode() { var hashNum = Math.Min(_data.Length, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(_data[i]); -#else - hash ^= BitConverter.DoubleToInt64Bits(_data[i]); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + _data[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } #region Elementary operations diff --git a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs index b9323970..858e2642 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs @@ -622,17 +622,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double { var values = _storage.Values; var hashNum = Math.Min(_storage.ValueCount, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(values[i]); -#else - hash ^= BitConverter.DoubleToInt64Bits(values[i]); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + values[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } /// diff --git a/src/Numerics/LinearAlgebra/Generic/Matrix.cs b/src/Numerics/LinearAlgebra/Generic/Matrix.cs index 7d6377ab..cef3cd26 100644 --- a/src/Numerics/LinearAlgebra/Generic/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Generic/Matrix.cs @@ -1430,21 +1430,18 @@ namespace MathNet.Numerics.LinearAlgebra.Generic /// public override int GetHashCode() { - var hashNum = Math.Min(RowCount * ColumnCount, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + var hashNum = Math.Min(RowCount*ColumnCount, 25); + int hash = 17; + unchecked { - var col = i % ColumnCount; - var row = (i - col) / RowCount; - -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(this[row, col].GetHashCode()); -#else - hash ^= BitConverter.DoubleToInt64Bits(this[row, col].GetHashCode()); -#endif + for (var i = 0; i < hashNum; i++) + { + var col = i%ColumnCount; + var row = (i - col)/RowCount; + hash = hash*31 + this[row, col].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } #endregion diff --git a/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs index 4b74c7ae..2ae82101 100644 --- a/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs @@ -219,17 +219,15 @@ namespace MathNet.Numerics.LinearAlgebra.Single public override int GetHashCode() { var hashNum = Math.Min(_data.Length, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(_data[i]); -#else - hash ^= BitConverter.DoubleToInt64Bits(_data[i]); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + _data[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } #region Elementary operations diff --git a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs index b356c696..53660deb 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs @@ -622,17 +622,15 @@ namespace MathNet.Numerics.LinearAlgebra.Single { var values = _storage.Values; var hashNum = Math.Min(_storage.ValueCount, 25); - long hash = 0; - for (var i = 0; i < hashNum; i++) + int hash = 17; + unchecked { -#if PORTABLE - hash ^= Precision.DoubleToInt64Bits(values[i]); -#else - hash ^= BitConverter.DoubleToInt64Bits(values[i]); -#endif + for (var i = 0; i < hashNum; i++) + { + hash = hash*31 + values[i].GetHashCode(); + } } - - return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4); + return hash; } /// diff --git a/src/UnitTests/LinearAlgebraTests/Complex/MatrixStructureTheory.cs b/src/UnitTests/LinearAlgebraTests/Complex/MatrixStructureTheory.cs new file mode 100644 index 00000000..6fd65dc7 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Complex/MatrixStructureTheory.cs @@ -0,0 +1,50 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex +{ + using LinearAlgebra.Complex; + using LinearAlgebra.Generic; + using NUnit.Framework; + using System.Numerics; + + [TestFixture] + public class MatrixStructureTheory : MatrixStructureTheory + { + [Datapoints] + Matrix[] _matrices = new Matrix[] + { + new DenseMatrix(new[,] {{1d, new Complex(1.1d, -4d), 2d}, {1d, 1d, 2d}, {1d, new Complex(1d,2d), 2d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d, -3.3d}, {0d, 1.1d, new Complex(2.2d, -1.2d)}, {-4.4d, 5.5d, 6.6d}}), + new DenseMatrix(new[,] {{new Complex(-1.1d, -2d), -2.2d, -3.3d, -4.4d}, {0d, 1.1d, 2.2d, 3.3d}, {1d, 2.1d, 6.2d, 4.3d}, {-4.4d, 5.5d, 6.6d, -7.7d}}), + new DenseMatrix(new[,] {{-1.1d, new Complex(-2.2d, 3.4d), -3.3d, -4.4d}, {-1.1d, -2.2d, -3.3d, -4.4d}, {-1.1d, -2.2d, -3.3d, -4.4d}, {-1.1d, -2.2d, -3.3d, -4.4d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d}, {Complex.Zero, 1.1d}, {-4.4d, 5.5d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d, -3.3d}, {0d, new Complex(1.1d, 0.1d), 2.2d}}), + new DenseMatrix(new[,] {{1d, 2d, 3d}, {2d, new Complex(2d, 2d), 0d}, {3d, Complex.Zero, 3d}}), + + new SparseMatrix(new[,] {{7d, 1d, 2d}, {1d, 1d, 2d}, {1d, 1d + Complex.ImaginaryOne, 2d}}), + new SparseMatrix(new[,] {{7d, 1d, 2d}, {new Complex(1d,2d), 0d, Complex.Zero}, {-2d, 0d, 0d}}), + new SparseMatrix(new[,] {{-1.1d, 0d, 0d}, {0d, new Complex(1.1d, 2d), 2.2d}}), + + new DiagonalMatrix(3, 3, new[] {new Complex(1d,1d), -2d, 1.5d}), + new DiagonalMatrix(3, 3, new[] {new Complex(1d,2d), 0d, -1.5d}), + + new UserDefinedMatrix(new[,] {{0d, 1d, 2d}, {-1d, 7.7d, 0d}, {-2d, Complex.Zero, 0d}}) + }; + + [Datapoints] + Complex[] scalars = new[] {new Complex(2d, 0d), new Complex(-1.5d, 3.5d), Complex.Zero}; + + protected override Matrix CreateDense(int rows, int columns) + { + return new DenseMatrix(rows, columns); + } + + protected override Matrix CreateSparse(int rows, int columns) + { + return new SparseMatrix(rows, columns); + } + + protected override Vector CreateVector(int size) + { + return new DenseVector(size); + } + } +} \ No newline at end of file diff --git a/src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.cs index 4e6a54ba..1795de5e 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.cs @@ -36,326 +36,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex /// public abstract partial class MatrixTests : MatrixLoader { - /// - /// Can clone a matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrix(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - var clone = matrix.Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can clone a matrix using ICloneable interface. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrixUsingICloneable(string name) - { - var matrix = TestMatrices[name]; - var clone = (Matrix)((ICloneable)matrix).Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can copy a matrix to another matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCopyTo(string name) - { - var matrix = TestMatrices[name]; - var copy = CreateMatrix(matrix.RowCount, matrix.ColumnCount); - matrix.CopyTo(copy); - - Assert.AreNotSame(matrix, copy); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], copy[i, j]); - } - } - } - - /// - /// Copy a matrix to another matrix fails when target is null. - /// - [Test] - public void CopyToWhenTargetIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Matrix target = null; - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more rows. - /// - [Test] - public void CopyToWhenTargetHasMoreRowsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more columns. - /// - [Test] - public void CopyToWhenTargetHasMoreColumnsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Can create a matrix. - /// - [Test] - public void CanCreateMatrix() - { - var expected = CreateMatrix(5, 6); - var actual = expected.CreateMatrix(5, 6); - Assert.AreEqual(expected.GetType(), actual.GetType(), "Matrices are same type."); - } - - /// - /// Can equate matrices. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanEquateMatrices(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - var matrix3 = CreateMatrix(TestData2D[name].GetLength(0), TestData2D[name].GetLength(1)); - Assert.IsTrue(matrix1.Equals(matrix1)); - Assert.IsTrue(matrix1.Equals(matrix2)); - Assert.IsFalse(matrix1.Equals(matrix3)); - Assert.IsFalse(matrix1.Equals(null)); - } - - /// - /// Create a matrix throws ArgumentOutOfRangeException if size is not positive. - /// - /// The number of rows. - /// The number of columns. - [TestCase(0, 2)] - [TestCase(2, 0)] - [TestCase(0, 0)] - [TestCase(-1, 1)] - [TestCase(1, -1)] - public void IfSizeIsNotPositiveThrowsArgumentException(int rows, int columns) - { - Assert.Throws(() => CreateMatrix(rows, columns)); - } - - /// - /// Testing for equality with non-matrix returns false. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void TestingForEqualityWithNonMatrixReturnsFalse(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - Assert.IsFalse(matrix.Equals(2)); - } - - /// - /// Can test for equality using Object.Equals. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanTestForEqualityUsingObjectEquals(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - Assert.IsTrue(matrix1.Equals((object)matrix2)); - } - - /// - /// Range check fails with wrong parameters. - /// - /// Row index. - /// Column index. - /// Matrix name. - [TestCase(-1, 1, "Singular3x3")] - [TestCase(1, -1, "Singular3x3")] - [TestCase(4, 2, "Square3x3")] - public void RangeCheckWithInvalidIndicesThrowsArgumentOutOfRangeException(int i, int j, string name) - { - Assert.Throws(() => { var x = TestMatrices[name][i, j]; }); - } - - /// - /// Can get matrix hash code. - /// - [Test] - public void CanMatrixGetHashCode() - { - var hash = TestMatrices["Singular3x3"].GetHashCode(); - } - - /// - /// Can clear matrix. - /// - [Test] - public void CanClearMatrix() - { - var matrix = TestMatrices["Singular3x3"].Clone(); - matrix.Clear(); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(Complex.Zero, matrix[i, j]); - } - } - } - - /// - /// Can get a row of a matrix. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRow(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = matrix.Row(rowIndex); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row throws ArgumentOutOfRange with negative index. - /// - [Test] - public void GetRowWithNegativeIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(-1)); - } - - /// - /// Get row throws ArgumentOutOfRangeException with overflowing row index. - /// - [Test] - public void GetRowWithOverflowingRowIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(matrix.RowCount)); - } - - /// - /// Can get row of a matrix into a result vector. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRowIntoResult(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = CreateVector(matrix.ColumnCount); - matrix.Row(rowIndex, row); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row of a matrix into null result vector throws ArgumentNullException. - /// - [Test] - public void GetRowWhenResultIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(0, null)); - } - - /// - /// Get row into a result with the negative row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithNegativeRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(-1, row)); - } - - /// - /// Get row into a vector with overflowing row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithOverflowingRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(matrix.RowCount, row)); - } - /// /// Can get a row at specific start position and length of a matrix into a vector. /// diff --git a/src/UnitTests/LinearAlgebraTests/Complex32/MatrixStructureTheory.cs b/src/UnitTests/LinearAlgebraTests/Complex32/MatrixStructureTheory.cs new file mode 100644 index 00000000..7d29f516 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Complex32/MatrixStructureTheory.cs @@ -0,0 +1,50 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 +{ + using LinearAlgebra.Complex32; + using LinearAlgebra.Generic; + using NUnit.Framework; + using Complex32 = Numerics.Complex32; + + [TestFixture] + public class MatrixStructureTheory : MatrixStructureTheory + { + [Datapoints] + Matrix[] _matrices = new Matrix[] + { + new DenseMatrix(new[,] {{1f, new Complex32(1.1f, -4f), 2f}, {1f, 1f, 2f}, {1f, new Complex32(1f,2f), 2f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f, -3.3f}, {0f, 1.1f, new Complex32(2.2f, -1.2f)}, {-4.4f, 5.5f, 6.6f}}), + new DenseMatrix(new[,] {{new Complex32(-1.1f, -2f), -2.2f, -3.3f, -4.4f}, {0f, 1.1f, 2.2f, 3.3f}, {1f, 2.1f, 6.2f, 4.3f}, {-4.4f, 5.5f, 6.6f, -7.7f}}), + new DenseMatrix(new[,] {{-1.1f, new Complex32(-2.2f, 3.4f), -3.3f, -4.4f}, {-1.1f, -2.2f, -3.3f, -4.4f}, {-1.1f, -2.2f, -3.3f, -4.4f}, {-1.1f, -2.2f, -3.3f, -4.4f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f}, {Complex32.Zero, 1.1f}, {-4.4f, 5.5f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f, -3.3f}, {0f, new Complex32(1.1f, 0.1f), 2.2f}}), + new DenseMatrix(new[,] {{1f, 2f, 3f}, {2f, new Complex32(2f, 2f), 0f}, {3f, Complex32.Zero, 3f}}), + + new SparseMatrix(new[,] {{7f, 1f, 2f}, {1f, 1f, 2f}, {1f, 1f + Complex32.ImaginaryOne, 2f}}), + new SparseMatrix(new[,] {{7f, 1f, 2f}, {new Complex32(1f,2f), 0f, Complex32.Zero}, {-2f, 0f, 0f}}), + new SparseMatrix(new[,] {{-1.1f, 0f, 0f}, {0f, new Complex32(1.1f, 2f), 2.2f}}), + + new DiagonalMatrix(3, 3, new[] {new Complex32(1f,1f), -2f, 1.5f}), + new DiagonalMatrix(3, 3, new[] {new Complex32(1f,2f), 0f, -1.5f}), + + new UserDefinedMatrix(new[,] {{0f, 1f, 2f}, {-1f, 7.7f, 0f}, {-2f, Complex32.Zero, 0f}}) + }; + + [Datapoints] + Complex32[] scalars = new[] { new Complex32(2f, 0f), new Complex32(-1.5f, 3.5f), Complex32.Zero }; + + protected override Matrix CreateDense(int rows, int columns) + { + return new DenseMatrix(rows, columns); + } + + protected override Matrix CreateSparse(int rows, int columns) + { + return new SparseMatrix(rows, columns); + } + + protected override Vector CreateVector(int size) + { + return new DenseVector(size); + } + } +} \ No newline at end of file diff --git a/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs index 58952d08..f5989d88 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs @@ -36,326 +36,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 /// public abstract partial class MatrixTests : MatrixLoader { - /// - /// Can clone a matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrix(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - var clone = matrix.Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can clone a matrix using ICloneable interface. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrixUsingICloneable(string name) - { - var matrix = TestMatrices[name]; - var clone = (Matrix)((ICloneable)matrix).Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can copy a matrix to another matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCopyTo(string name) - { - var matrix = TestMatrices[name]; - var copy = CreateMatrix(matrix.RowCount, matrix.ColumnCount); - matrix.CopyTo(copy); - - Assert.AreNotSame(matrix, copy); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], copy[i, j]); - } - } - } - - /// - /// Copy a matrix to another matrix fails when target is null. - /// - [Test] - public void CopyToWhenTargetIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Matrix target = null; - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more rows. - /// - [Test] - public void CopyToWhenTargetHasMoreRowsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more columns. - /// - [Test] - public void CopyToWhenTargetHasMoreColumnsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Can create a matrix. - /// - [Test] - public void CanCreateMatrix() - { - var expected = CreateMatrix(5, 6); - var actual = expected.CreateMatrix(5, 6); - Assert.AreEqual(expected.GetType(), actual.GetType(), "Matrices are same type."); - } - - /// - /// Can equate matrices. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanEquateMatrices(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - var matrix3 = CreateMatrix(TestData2D[name].GetLength(0), TestData2D[name].GetLength(1)); - Assert.IsTrue(matrix1.Equals(matrix1)); - Assert.IsTrue(matrix1.Equals(matrix2)); - Assert.IsFalse(matrix1.Equals(matrix3)); - Assert.IsFalse(matrix1.Equals(null)); - } - - /// - /// Create a matrix throws ArgumentOutOfRangeException if size is not positive. - /// - /// The number of rows. - /// The number of columns. - [TestCase(0, 2)] - [TestCase(2, 0)] - [TestCase(0, 0)] - [TestCase(-1, 1)] - [TestCase(1, -1)] - public void IfSizeIsNotPositiveThrowsArgumentException(int rows, int columns) - { - Assert.Throws(() => CreateMatrix(rows, columns)); - } - - /// - /// Testing for equality with non-matrix returns false. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void TestingForEqualityWithNonMatrixReturnsFalse(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - Assert.IsFalse(matrix.Equals(2)); - } - - /// - /// Can test for equality using Object.Equals. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanTestForEqualityUsingObjectEquals(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - Assert.IsTrue(matrix1.Equals((object)matrix2)); - } - - /// - /// Range check fails with wrong parameters. - /// - /// Row index. - /// Column index. - /// Matrix name. - [TestCase(-1, 1, "Singular3x3")] - [TestCase(1, -1, "Singular3x3")] - [TestCase(4, 2, "Square3x3")] - public void RangeCheckWithInvalidIndicesThrowsArgumentOutOfRangeException(int i, int j, string name) - { - Assert.Throws(() => { var x = TestMatrices[name][i, j]; }); - } - - /// - /// Can get matrix hash code. - /// - [Test] - public void CanMatrixGetHashCode() - { - var hash = TestMatrices["Singular3x3"].GetHashCode(); - } - - /// - /// Can clear matrix. - /// - [Test] - public void CanClearMatrix() - { - var matrix = TestMatrices["Singular3x3"].Clone(); - matrix.Clear(); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(Complex32.Zero, matrix[i, j]); - } - } - } - - /// - /// Can get a row of a matrix. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRow(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = matrix.Row(rowIndex); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row throws ArgumentOutOfRange with negative index. - /// - [Test] - public void GetRowWithNegativeIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(-1)); - } - - /// - /// Get row throws ArgumentOutOfRangeException with overflowing row index. - /// - [Test] - public void GetRowWithOverflowingRowIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(matrix.RowCount)); - } - - /// - /// Can get row of a matrix into a result vector. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRowIntoResult(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = CreateVector(matrix.ColumnCount); - matrix.Row(rowIndex, row); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row of a matrix into null result vector throws ArgumentNullException. - /// - [Test] - public void GetRowWhenResultIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(0, null)); - } - - /// - /// Get row into a result with the negative row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithNegativeRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(-1, row)); - } - - /// - /// Get row into a vector with overflowing row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithOverflowingRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(matrix.RowCount, row)); - } - /// /// Can get a row at specific start position and length of a matrix into a vector. /// diff --git a/src/UnitTests/LinearAlgebraTests/Double/MatrixStructureTheory.cs b/src/UnitTests/LinearAlgebraTests/Double/MatrixStructureTheory.cs new file mode 100644 index 00000000..380ff9e6 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Double/MatrixStructureTheory.cs @@ -0,0 +1,49 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double +{ + using LinearAlgebra.Double; + using LinearAlgebra.Generic; + using NUnit.Framework; + + [TestFixture] + public class MatrixStructureTheory : MatrixStructureTheory + { + [Datapoints] + Matrix[] _matrices = new Matrix[] + { + new DenseMatrix(new[,] {{1d, 1d, 2d}, {1d, 1d, 2d}, {1d, 1d, 2d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d, -3.3d}, {0d, 1.1d, 2.2d}, {-4.4d, 5.5d, 6.6d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d, -3.3d, -4.4d}, {0d, 1.1d, 2.2d, 3.3d}, {1d, 2.1d, 6.2d, 4.3d}, {-4.4d, 5.5d, 6.6d, -7.7d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d, -3.3d, -4.4d}, {-1.1d, -2.2d, -3.3d, -4.4d}, {-1.1d, -2.2d, -3.3d, -4.4d}, {-1.1d, -2.2d, -3.3d, -4.4d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d}, {0d, 1.1d}, {-4.4d, 5.5d}}), + new DenseMatrix(new[,] {{-1.1d, -2.2d, -3.3d}, {0d, 1.1d, 2.2d}}), + new DenseMatrix(new[,] {{1d, 2d, 3d}, {2d, 2d, 0d}, {3d, 0d, 3d}}), + + new SparseMatrix(new[,] {{7d, 1d, 2d}, {1d, 1d, 2d}, {1d, 1d, 2d}}), + new SparseMatrix(new[,] {{7d, 1d, 2d}, {1d, 0d, 0d}, {-2d, 0d, 0d}}), + new SparseMatrix(new[,] {{-1.1d, 0d, 0d}, {0d, 1.1d, 2.2d}}), + + new DiagonalMatrix(3, 3, new[] {1d, -2d, 1.5d}), + new DiagonalMatrix(3, 3, new[] {1d, 0d, -1.5d}), + + new UserDefinedMatrix(new[,] {{0d, 1d, 2d}, {-1d, 7.7d, 0d}, {-2d, 0d, 0d}}) + }; + + [Datapoints] + double[] _scalars = new[] {2d, -1.5d, 0d}; + + protected override Matrix CreateDense(int rows, int columns) + { + return new DenseMatrix(rows, columns); + } + + protected override Matrix CreateSparse(int rows, int columns) + { + return new SparseMatrix(rows, columns); + } + + protected override Vector CreateVector(int size) + { + return new DenseVector(size); + } + } +} \ No newline at end of file diff --git a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs index 45c04cd5..92b4c458 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs @@ -35,326 +35,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double /// public abstract partial class MatrixTests : MatrixLoader { - /// - /// Can clone a matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrix(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - var clone = matrix.Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can clone a matrix using ICloneable interface. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrixUsingICloneable(string name) - { - var matrix = TestMatrices[name]; - var clone = (Matrix)((ICloneable)matrix).Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can copy a matrix to another matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCopyTo(string name) - { - var matrix = TestMatrices[name]; - var copy = CreateMatrix(matrix.RowCount, matrix.ColumnCount); - matrix.CopyTo(copy); - - Assert.AreNotSame(matrix, copy); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], copy[i, j]); - } - } - } - - /// - /// Copy a matrix to another matrix fails when target is null. - /// - [Test] - public void CopyToWhenTargetIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Matrix target = null; - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more rows. - /// - [Test] - public void CopyToWhenTargetHasMoreRowsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more columns. - /// - [Test] - public void CopyToWhenTargetHasMoreColumnsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Can create a matrix. - /// - [Test] - public void CanCreateMatrix() - { - var expected = CreateMatrix(5, 6); - var actual = expected.CreateMatrix(5, 6); - Assert.AreEqual(expected.GetType(), actual.GetType(), "Matrices are same type."); - } - - /// - /// Can equate matrices. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanEquateMatrices(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - var matrix3 = CreateMatrix(TestData2D[name].GetLength(0), TestData2D[name].GetLength(1)); - Assert.IsTrue(matrix1.Equals(matrix1)); - Assert.IsTrue(matrix1.Equals(matrix2)); - Assert.IsFalse(matrix1.Equals(matrix3)); - Assert.IsFalse(matrix1.Equals(null)); - } - - /// - /// Create a matrix throws ArgumentOutOfRangeException if size is not positive. - /// - /// The number of rows. - /// The number of columns. - [TestCase(0, 2)] - [TestCase(2, 0)] - [TestCase(0, 0)] - [TestCase(-1, 1)] - [TestCase(1, -1)] - public void IfSizeIsNotPositiveThrowsArgumentException(int rows, int columns) - { - Assert.Throws(() => CreateMatrix(rows, columns)); - } - - /// - /// Testing for equality with non-matrix returns false. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void TestingForEqualityWithNonMatrixReturnsFalse(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - Assert.IsFalse(matrix.Equals(2)); - } - - /// - /// Can test for equality using Object.Equals. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanTestForEqualityUsingObjectEquals(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - Assert.IsTrue(matrix1.Equals((object)matrix2)); - } - - /// - /// Range check fails with wrong parameters. - /// - /// Row index. - /// Column index. - /// Matrix name. - [TestCase(-1, 1, "Singular3x3")] - [TestCase(1, -1, "Singular3x3")] - [TestCase(4, 2, "Square3x3")] - public void RangeCheckWithInvalidIndicesThrowsArgumentOutOfRangeException(int i, int j, string name) - { - Assert.Throws(() => { var x = TestMatrices[name][i, j]; }); - } - - /// - /// Can get matrix hash code. - /// - [Test] - public void CanMatrixGetHashCode() - { - var hash = TestMatrices["Singular3x3"].GetHashCode(); - } - - /// - /// Can clear matrix. - /// - [Test] - public void CanClearMatrix() - { - var matrix = TestMatrices["Singular3x3"].Clone(); - matrix.Clear(); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(0, matrix[i, j]); - } - } - } - - /// - /// Can get a row of a matrix. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRow(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = matrix.Row(rowIndex); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row throws ArgumentOutOfRange with negative index. - /// - [Test] - public void GetRowWithNegativeIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(-1)); - } - - /// - /// Get row throws ArgumentOutOfRangeException with overflowing row index. - /// - [Test] - public void GetRowWithOverflowingRowIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(matrix.RowCount)); - } - - /// - /// Can get row of a matrix into a result vector. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRowIntoResult(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = CreateVector(matrix.ColumnCount); - matrix.Row(rowIndex, row); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row of a matrix into null result vector throws ArgumentNullException. - /// - [Test] - public void GetRowWhenResultIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(0, null)); - } - - /// - /// Get row into a result with the negative row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithNegativeRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(-1, row)); - } - - /// - /// Get row into a vector with overflowing row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithOverflowingRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(matrix.RowCount, row)); - } - /// /// Can get a row at specific start position and length of a matrix into a vector. /// diff --git a/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs b/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs new file mode 100644 index 00000000..1f81a120 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs @@ -0,0 +1,159 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests +{ + using System; + using LinearAlgebra.Generic; + using NUnit.Framework; + + [TestFixture] + public abstract class MatrixStructureTheory + where T : struct, IEquatable, IFormattable + { + protected abstract Matrix CreateDense(int rows, int columns); + protected abstract Matrix CreateSparse(int rows, int columns); + protected abstract Vector CreateVector(int size); + + [Theory, Timeout(200)] + public void IsEqualToItself(Matrix matrix) + { + Assert.That(matrix, Is.EqualTo(matrix)); + Assert.IsTrue(matrix.Equals(matrix)); + Assert.IsTrue(matrix.Equals((object) matrix)); + Assert.IsTrue(((object) matrix).Equals(matrix)); + Assert.IsTrue(matrix == (object) matrix); + Assert.IsTrue((object) matrix == matrix); + } + + [Theory, Timeout(200)] + public void IsNotEqualToOthers(Matrix left, Matrix right) + { + // IF (assuming we don't have duplicate data points) + Assume.That(left, Is.Not.SameAs(right)); + + // THEN + Assert.That(left, Is.Not.EqualTo(right)); + Assert.IsFalse(left.Equals(right)); + Assert.IsFalse(left.Equals((object) right)); + Assert.IsFalse(((object) left).Equals(right)); + Assert.IsFalse(left == (object) right); + Assert.IsFalse((object) left == right); + } + + [Theory, Timeout(200)] + public void IsNotEqualToNonMatrixType(Matrix matrix) + { + Assert.That(matrix, Is.Not.EqualTo(2)); + Assert.IsFalse(matrix.Equals(2)); + Assert.IsFalse(matrix.Equals((object)2)); + Assert.IsFalse(((object)matrix).Equals(2)); + Assert.IsFalse(matrix == (object)2); + } + + [Theory, Timeout(200)] + public void CanClone(Matrix matrix) + { + var clone = matrix.Clone(); + Assert.That(clone, Is.Not.SameAs(matrix)); + Assert.That(clone, Is.EqualTo(matrix)); + Assert.That(clone.RowCount, Is.EqualTo(matrix.RowCount)); + Assert.That(clone.ColumnCount, Is.EqualTo(matrix.ColumnCount)); + } + + [Theory, Timeout(200)] + public void CanCloneUsingICloneable(Matrix matrix) + { + var clone = (Matrix) ((ICloneable) matrix).Clone(); + Assert.That(clone, Is.Not.SameAs(matrix)); + Assert.That(clone, Is.EqualTo(matrix)); + Assert.That(clone.RowCount, Is.EqualTo(matrix.RowCount)); + Assert.That(clone.ColumnCount, Is.EqualTo(matrix.ColumnCount)); + } + + [Theory, Timeout(200)] + public void CanCopyTo(Matrix matrix) + { + var dense = CreateDense(matrix.RowCount, matrix.ColumnCount); + matrix.CopyTo(dense); + Assert.That(dense, Is.EqualTo(matrix)); + + var sparse = CreateSparse(matrix.RowCount, matrix.ColumnCount); + matrix.CopyTo(sparse); + Assert.That(sparse, Is.EqualTo(matrix)); + + // null arg + Assert.That(() => matrix.CopyTo(null), Throws.InstanceOf()); + + // bad arg + Assert.That(() => matrix.CopyTo(CreateDense(matrix.RowCount + 1, matrix.ColumnCount)), Throws.ArgumentException); + Assert.That(() => matrix.CopyTo(CreateDense(matrix.RowCount, matrix.ColumnCount + 1)), Throws.ArgumentException); + } + + [Theory, Timeout(200)] + public void CanCreateSameType(Matrix matrix) + { + var empty = matrix.CreateMatrix(5, 6); + Assert.That(empty, Is.EqualTo(CreateDense(5, 6))); + Assert.That(empty.GetType(), Is.EqualTo(matrix.GetType())); + + Assert.That(() => matrix.CreateMatrix(0, 2), Throws.InstanceOf()); + Assert.That(() => matrix.CreateMatrix(2, 0), Throws.InstanceOf()); + Assert.That(() => matrix.CreateMatrix(-1, -1), Throws.InstanceOf()); + } + + [Theory, Timeout(200)] + public void CanGetHashCode(Matrix matrix) + { + Assert.That(matrix.GetHashCode(), Is.Not.EqualTo(matrix.CreateMatrix(matrix.RowCount, matrix.ColumnCount).GetHashCode())); + } + + [Theory, Timeout(200)] + public void CanClear(Matrix matrix) + { + var cleared = matrix.Clone(); + cleared.Clear(); + Assert.That(cleared, Is.EqualTo(matrix.CreateMatrix(matrix.RowCount, matrix.ColumnCount))); + } + + [Theory, Timeout(200)] + public void CanGetFieldsByIndex(Matrix matrix) + { + Assert.That(() => { var x = matrix[0, 0]; }, Throws.Nothing); + Assert.That(() => { var x = matrix[0, matrix.ColumnCount - 1]; }, Throws.Nothing); + Assert.That(() => { var x = matrix[matrix.RowCount - 1, 0]; }, Throws.Nothing); + + Assert.That(() => { var x = matrix[-1, 1]; }, Throws.InstanceOf()); + Assert.That(() => { var x = matrix[1, -1]; }, Throws.InstanceOf()); + Assert.That(() => { var x = matrix[0, matrix.ColumnCount]; }, Throws.InstanceOf()); + } + + [Theory, Timeout(200)] + public void CanGetRow(Matrix matrix, [Values(0, 1, 1000)]int rowIndex) + { + var actualRow = Math.Min(rowIndex, matrix.RowCount - 1); + var row = matrix.Row(actualRow); + Assert.That(row.Count, Is.EqualTo(matrix.ColumnCount)); + for (var j = 0; j < matrix.ColumnCount; j++) + { + Assert.AreEqual(matrix[actualRow, j], row[j]); + } + + Assert.That(() => { matrix.Row(-1); }, Throws.InstanceOf()); + Assert.That(() => { matrix.Row(matrix.RowCount); }, Throws.InstanceOf()); + } + + [Theory, Timeout(200)] + public void CanGetRowIntoResult(Matrix matrix) + { + var row = CreateVector(matrix.ColumnCount); + matrix.Row(0, row); + + for (var j = 0; j < matrix.ColumnCount; j++) + { + Assert.AreEqual(matrix[0, j], row[j]); + } + + Assert.That(() => matrix.Row(0, null), Throws.InstanceOf()); + Assert.That(() => matrix.Row(-1, row), Throws.InstanceOf()); + Assert.That(() => matrix.Row(matrix.RowCount, row), Throws.InstanceOf()); + } + } +} diff --git a/src/UnitTests/LinearAlgebraTests/Single/MatrixStructureTheory.cs b/src/UnitTests/LinearAlgebraTests/Single/MatrixStructureTheory.cs new file mode 100644 index 00000000..c55d3d20 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Single/MatrixStructureTheory.cs @@ -0,0 +1,49 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single +{ + using LinearAlgebra.Single; + using LinearAlgebra.Generic; + using NUnit.Framework; + + [TestFixture] + public class MatrixStructureTheory : MatrixStructureTheory + { + [Datapoints] + Matrix[] _matrices = new Matrix[] + { + new DenseMatrix(new[,] {{1f, 1f, 2f}, {1f, 1f, 2f}, {1f, 1f, 2f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f, -3.3f}, {0f, 1.1f, 2.2f}, {-4.4f, 5.5f, 6.6f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f, -3.3f, -4.4f}, {0f, 1.1f, 2.2f, 3.3f}, {1f, 2.1f, 6.2f, 4.3f}, {-4.4f, 5.5f, 6.6f, -7.7f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f, -3.3f, -4.4f}, {-1.1f, -2.2f, -3.3f, -4.4f}, {-1.1f, -2.2f, -3.3f, -4.4f}, {-1.1f, -2.2f, -3.3f, -4.4f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f}, {0f, 1.1f}, {-4.4f, 5.5f}}), + new DenseMatrix(new[,] {{-1.1f, -2.2f, -3.3f}, {0f, 1.1f, 2.2f}}), + new DenseMatrix(new[,] {{1f, 2f, 3f}, {2f, 2f, 0f}, {3f, 0f, 3f}}), + + new SparseMatrix(new[,] {{7f, 1f, 2f}, {1f, 1f, 2f}, {1f, 1f, 2f}}), + new SparseMatrix(new[,] {{7f, 1f, 2f}, {1f, 0f, 0f}, {-2f, 0f, 0f}}), + new SparseMatrix(new[,] {{-1.1f, 0f, 0f}, {0f, 1.1f, 2.2f}}), + + new DiagonalMatrix(3, 3, new[] {1f, -2f, 1.5f}), + new DiagonalMatrix(3, 3, new[] {1f, 0f, -1.5f}), + + new UserDefinedMatrix(new[,] {{0f, 1f, 2f}, {-1f, 7.7f, 0f}, {-2f, 0f, 0f}}) + }; + + [Datapoints] + float[] _scalars = new[] {2f, -1.5f, 0f}; + + protected override Matrix CreateDense(int rows, int columns) + { + return new DenseMatrix(rows, columns); + } + + protected override Matrix CreateSparse(int rows, int columns) + { + return new SparseMatrix(rows, columns); + } + + protected override Vector CreateVector(int size) + { + return new DenseVector(size); + } + } +} diff --git a/src/UnitTests/LinearAlgebraTests/Single/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Single/MatrixTests.cs index c7dd7b7a..9843faf4 100644 --- a/src/UnitTests/LinearAlgebraTests/Single/MatrixTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Single/MatrixTests.cs @@ -35,326 +35,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single /// public abstract partial class MatrixTests : MatrixLoader { - /// - /// Can clone a matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrix(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - var clone = matrix.Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can clone a matrix using ICloneable interface. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCloneMatrixUsingICloneable(string name) - { - var matrix = TestMatrices[name]; - var clone = (Matrix)((ICloneable)matrix).Clone(); - - Assert.AreNotSame(matrix, clone); - Assert.AreEqual(matrix.RowCount, clone.RowCount); - Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], clone[i, j]); - } - } - } - - /// - /// Can copy a matrix to another matrix. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanCopyTo(string name) - { - var matrix = TestMatrices[name]; - var copy = CreateMatrix(matrix.RowCount, matrix.ColumnCount); - matrix.CopyTo(copy); - - Assert.AreNotSame(matrix, copy); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[i, j], copy[i, j]); - } - } - } - - /// - /// Copy a matrix to another matrix fails when target is null. - /// - [Test] - public void CopyToWhenTargetIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Matrix target = null; - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more rows. - /// - [Test] - public void CopyToWhenTargetHasMoreRowsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Copy a matrix to another matrix fails when target has more columns. - /// - [Test] - public void CopyToWhenTargetHasMoreColumnsThrowsArgumentException() - { - var matrix = TestMatrices["Singular3x3"]; - var target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount); - Assert.Throws(() => matrix.CopyTo(target)); - } - - /// - /// Can create a matrix. - /// - [Test] - public void CanCreateMatrix() - { - var expected = CreateMatrix(5, 6); - var actual = expected.CreateMatrix(5, 6); - Assert.AreEqual(expected.GetType(), actual.GetType(), "Matrices are same type."); - } - - /// - /// Can equate matrices. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanEquateMatrices(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - var matrix3 = CreateMatrix(TestData2D[name].GetLength(0), TestData2D[name].GetLength(1)); - Assert.IsTrue(matrix1.Equals(matrix1)); - Assert.IsTrue(matrix1.Equals(matrix2)); - Assert.IsFalse(matrix1.Equals(matrix3)); - Assert.IsFalse(matrix1.Equals(null)); - } - - /// - /// Create a matrix throws ArgumentOutOfRangeException if size is not positive. - /// - /// The number of rows. - /// The number of columns. - [TestCase(0, 2)] - [TestCase(2, 0)] - [TestCase(0, 0)] - [TestCase(-1, 1)] - [TestCase(1, -1)] - public void IfSizeIsNotPositiveThrowsArgumentException(int rows, int columns) - { - Assert.Throws(() => CreateMatrix(rows, columns)); - } - - /// - /// Testing for equality with non-matrix returns false. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void TestingForEqualityWithNonMatrixReturnsFalse(string name) - { - var matrix = CreateMatrix(TestData2D[name]); - Assert.IsFalse(matrix.Equals(2)); - } - - /// - /// Can test for equality using Object.Equals. - /// - /// Matrix name. - [TestCase("Singular3x3")] - [TestCase("Square3x3")] - [TestCase("Square4x4")] - [TestCase("Tall3x2")] - [TestCase("Wide2x3")] - public void CanTestForEqualityUsingObjectEquals(string name) - { - var matrix1 = CreateMatrix(TestData2D[name]); - var matrix2 = CreateMatrix(TestData2D[name]); - Assert.IsTrue(matrix1.Equals((object)matrix2)); - } - - /// - /// Range check fails with wrong parameters. - /// - /// Row index. - /// Column index. - /// Matrix name. - [TestCase(-1, 1, "Singular3x3")] - [TestCase(1, -1, "Singular3x3")] - [TestCase(4, 2, "Square3x3")] - public void RangeCheckWithInvalidIndicesThrowsArgumentOutOfRangeException(int i, int j, string name) - { - Assert.Throws(() => { var x = TestMatrices[name][i, j]; }); - } - - /// - /// Can get matrix hash code. - /// - [Test] - public void CanMatrixGetHashCode() - { - var hash = TestMatrices["Singular3x3"].GetHashCode(); - } - - /// - /// Can clear matrix. - /// - [Test] - public void CanClearMatrix() - { - var matrix = TestMatrices["Singular3x3"].Clone(); - matrix.Clear(); - for (var i = 0; i < matrix.RowCount; i++) - { - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(0, matrix[i, j]); - } - } - } - - /// - /// Can get a row of a matrix. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRow(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = matrix.Row(rowIndex); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row throws ArgumentOutOfRange with negative index. - /// - [Test] - public void GetRowWithNegativeIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(-1)); - } - - /// - /// Get row throws ArgumentOutOfRangeException with overflowing row index. - /// - [Test] - public void GetRowWithOverflowingRowIndexThrowsArgumentOutOfRange() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(matrix.RowCount)); - } - - /// - /// Can get row of a matrix into a result vector. - /// - /// Row index. - /// Matrix name. - [TestCase(0, "Singular3x3")] - [TestCase(1, "Square3x3")] - [TestCase(2, "Square3x3")] - public void CanGetRowIntoResult(int rowIndex, string name) - { - var matrix = TestMatrices[name]; - var row = CreateVector(matrix.ColumnCount); - matrix.Row(rowIndex, row); - - Assert.AreEqual(matrix.ColumnCount, row.Count); - for (var j = 0; j < matrix.ColumnCount; j++) - { - Assert.AreEqual(matrix[rowIndex, j], row[j]); - } - } - - /// - /// Get row of a matrix into null result vector throws ArgumentNullException. - /// - [Test] - public void GetRowWhenResultIsNullThrowsArgumentNullException() - { - var matrix = TestMatrices["Singular3x3"]; - Assert.Throws(() => matrix.Row(0, null)); - } - - /// - /// Get row into a result with the negative row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithNegativeRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(-1, row)); - } - - /// - /// Get row into a vector with overflowing row index throws ArgumentOutOfRangeException. - /// - [Test] - public void GetRowIntoResultWithOverflowingRowIndexThrowsArgumentOutOfRangeException() - { - var matrix = TestMatrices["Singular3x3"]; - var row = CreateVector(matrix.ColumnCount); - Assert.Throws(() => matrix.Row(matrix.RowCount, row)); - } - /// /// Can get a row at specific start position and length of a matrix into a vector. /// diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 7116a215..a5ddecd6 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -197,6 +197,7 @@ Code + Code @@ -344,6 +345,7 @@ Code + Code @@ -427,6 +429,7 @@ Code + Code @@ -573,6 +576,7 @@ Code + Code @@ -637,6 +641,7 @@ Code + Code