From 04d0a76d84e5e6476dc5766e5c961eb215495db4 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Fri, 1 Jan 2021 12:25:19 +0100 Subject: [PATCH] Linear Algebra: Matrix Resize --- .../MatrixStructureTheory.Reform.cs | 36 +++++++++++++++++++ src/Numerics/LinearAlgebra/Matrix.cs | 14 ++++++++ .../LinearAlgebra/Storage/MatrixStorage.cs | 11 ++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/Numerics.Tests/LinearAlgebraTests/MatrixStructureTheory.Reform.cs b/src/Numerics.Tests/LinearAlgebraTests/MatrixStructureTheory.Reform.cs index 76275a15..7dd6ed66 100644 --- a/src/Numerics.Tests/LinearAlgebraTests/MatrixStructureTheory.Reform.cs +++ b/src/Numerics.Tests/LinearAlgebraTests/MatrixStructureTheory.Reform.cs @@ -377,5 +377,41 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests Assert.That(() => left.DiagonalStack(right, Matrix.Build.Dense(left.RowCount + right.RowCount, left.ColumnCount + right.ColumnCount + 1)), Throws.ArgumentException); Assert.That(() => left.DiagonalStack(right, Matrix.Build.Dense(left.RowCount + right.RowCount, left.ColumnCount + right.ColumnCount - 1)), Throws.ArgumentException); } + + [Theory] + public void CanResize(TestMatrix testMatrix) + { + Matrix matrix = Get(testMatrix); + + var moreRows = matrix.Resize(matrix.RowCount + 2, matrix.ColumnCount); + Assert.That(moreRows.RowCount, Is.EqualTo(matrix.RowCount + 2)); + Assert.That(moreRows.ColumnCount, Is.EqualTo(matrix.ColumnCount)); + Assert.That(moreRows.SubMatrix(0, matrix.RowCount, 0, matrix.ColumnCount), Is.EqualTo(matrix)); + + var moreCols = matrix.Resize(matrix.RowCount, matrix.ColumnCount + 2); + Assert.That(moreCols.RowCount, Is.EqualTo(matrix.RowCount)); + Assert.That(moreCols.ColumnCount, Is.EqualTo(matrix.ColumnCount + 2)); + Assert.That(moreCols.SubMatrix(0, matrix.RowCount, 0, matrix.ColumnCount), Is.EqualTo(matrix)); + + if (matrix.RowCount >= 1) + { + var lessRows = matrix.Resize(matrix.RowCount - 1, matrix.ColumnCount); + Assert.That(lessRows.RowCount, Is.EqualTo(matrix.RowCount - 1)); + Assert.That(lessRows.ColumnCount, Is.EqualTo(matrix.ColumnCount)); + Assert.That(lessRows, Is.EqualTo(matrix.SubMatrix(0, matrix.RowCount - 1, 0, matrix.ColumnCount))); + } + + if (matrix.ColumnCount >= 1) + { + var lessCols = matrix.Resize(matrix.RowCount, matrix.ColumnCount - 1); + Assert.That(lessCols.RowCount, Is.EqualTo(matrix.RowCount)); + Assert.That(lessCols.ColumnCount, Is.EqualTo(matrix.ColumnCount - 1)); + Assert.That(lessCols, Is.EqualTo(matrix.SubMatrix(0, matrix.RowCount, 0, matrix.ColumnCount - 1))); + } + + var empty = matrix.Resize(0, 0); + Assert.That(empty.RowCount, Is.EqualTo(0)); + Assert.That(empty.ColumnCount, Is.EqualTo(0)); + } } } diff --git a/src/Numerics/LinearAlgebra/Matrix.cs b/src/Numerics/LinearAlgebra/Matrix.cs index 2cb7091b..880fb040 100644 --- a/src/Numerics/LinearAlgebra/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Matrix.cs @@ -999,6 +999,20 @@ namespace MathNet.Numerics.LinearAlgebra } } + /// + /// Creates a new matrix with the desired size and copies this matrix to it. + /// Values which no longer exist in the new matrix are ignored, new values are set to zero. + /// + /// The number of rows of the new matrix. + /// The number of columns of the new matrix. + /// A new matrix with the desired rows and columns. + public Matrix Resize(int rowCount, int columnCount) + { + var result = Build.SameAs(this, rowCount, columnCount, fullyMutable: true); + Storage.CopySubMatrixTo(result.Storage, 0, 0, Math.Min(RowCount, rowCount), 0, 0, Math.Min(ColumnCount, columnCount), ExistingData.AssumeZeros); + return result; + } + /// /// Returns the transpose of this matrix. /// diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs index 7d07c53e..63663650 100644 --- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs @@ -52,12 +52,12 @@ namespace MathNet.Numerics.LinearAlgebra.Storage { if (rowCount < 0) { - throw new ArgumentOutOfRangeException(nameof(rowCount), "The number of rows of a matrix must be positive."); + throw new ArgumentOutOfRangeException(nameof(rowCount), "The number of rows of a matrix must be non-negative."); } if (columnCount < 0) { - throw new ArgumentOutOfRangeException(nameof(columnCount), "The number of columns of a matrix must be positive."); + throw new ArgumentOutOfRangeException(nameof(columnCount), "The number of columns of a matrix must be non-negative."); } RowCount = rowCount; @@ -355,6 +355,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return; } + if (sourceRowIndex == 0 && targetRowIndex == 0 && rowCount == RowCount && rowCount == target.RowCount + && sourceColumnIndex == 0 && targetColumnIndex == 0 && columnCount == ColumnCount && columnCount == target.ColumnCount) + { + CopyTo(target); + return; + } + if (ReferenceEquals(this, target)) { throw new NotSupportedException();