From 519b0baf22d73387705f7cab0e26a2b39a5dfdf4 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Fri, 2 May 2014 16:14:03 +0200 Subject: [PATCH] LA: clear a set of rows or columns at storage level --- src/Numerics/LinearAlgebra/Matrix.cs | 52 +++++++++++++++++-- .../Storage/DenseColumnMajorMatrixStorage.cs | 20 +++++++ .../Storage/DiagonalMatrixStorage.cs | 16 ++++++ .../LinearAlgebra/Storage/MatrixStorage.cs | 24 +++++++++ .../SparseCompressedRowMatrixStorage.cs | 33 +++++++++++- .../MatrixStructureTheory.cs | 30 +++++++++-- 6 files changed, 165 insertions(+), 10 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Matrix.cs b/src/Numerics/LinearAlgebra/Matrix.cs index 713d3596..dfd0bd00 100644 --- a/src/Numerics/LinearAlgebra/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Matrix.cs @@ -146,6 +146,19 @@ namespace MathNet.Numerics.LinearAlgebra Storage.Clear(); } + /// + /// Sets all values of a row to zero. + /// + public void ClearRow(int rowIndex) + { + if (rowIndex < 0 || rowIndex >= RowCount) + { + throw new ArgumentOutOfRangeException("rowIndex"); + } + + Storage.Clear(rowIndex, 1, 0, ColumnCount); + } + /// /// Sets all values of a column to zero. /// @@ -160,16 +173,45 @@ namespace MathNet.Numerics.LinearAlgebra } /// - /// Sets all values of a row to zero. + /// Sets all values for all of the chosen rows to zero. /// - public void ClearRow(int rowIndex) + public void ClearRows(params int[] rowIndices) { - if (rowIndex < 0 || rowIndex >= RowCount) + if (rowIndices.Length == 0) { - throw new ArgumentOutOfRangeException("rowIndex"); + return; } - Storage.Clear(rowIndex, 1, 0, ColumnCount); + for (int k = 0; k < rowIndices.Length; k++) + { + if (rowIndices[k] < 0 || rowIndices[k] >= RowCount) + { + throw new ArgumentOutOfRangeException("rowIndices"); + } + } + + Storage.ClearRows(rowIndices); + } + + /// + /// Sets all values for all of the chosen columns to zero. + /// + public void ClearColumns(params int[] columnIndices) + { + if (columnIndices.Length == 0) + { + return; + } + + for (int k = 0; k < columnIndices.Length; k++) + { + if (columnIndices[k] < 0 || columnIndices[k] >= ColumnCount) + { + throw new ArgumentOutOfRangeException("columnIndices"); + } + } + + Storage.ClearColumns(columnIndices); } /// diff --git a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs index ab1daa7c..ac284a4c 100644 --- a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs @@ -127,6 +127,26 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + public override void ClearRows(int[] rowIndices) + { + for (var j = 0; j < ColumnCount; j++) + { + int offset = j*RowCount; + for (var k = 0; k < rowIndices.Length; k++) + { + Data[offset + rowIndices[k]] = Zero; + } + } + } + + public override void ClearColumns(int[] columnIndices) + { + for (int k = 0; k < columnIndices.Length; k++) + { + Array.Clear(Data, columnIndices[k]*RowCount, RowCount); + } + } + // INITIALIZATION public static DenseColumnMajorMatrixStorage OfMatrix(MatrixStorage matrix) diff --git a/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs index 2e1efec5..9a4bc881 100644 --- a/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs @@ -130,6 +130,22 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + public override void ClearRows(int[] rowIndices) + { + for (int i = 0; i < rowIndices.Length; i++) + { + Data[rowIndices[i]] = Zero; + } + } + + public override void ClearColumns(int[] columnIndices) + { + for (int i = 0; i < columnIndices.Length; i++) + { + Data[columnIndices[i]] = Zero; + } + } + /// /// Indicates whether the current object is equal to another object of the same type. /// diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs index 16e2b98f..1156a348 100644 --- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs @@ -150,6 +150,30 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + public virtual void ClearRows(int[] rowIndices) + { + for (var k = 0; k < rowIndices.Length; k++) + { + int row = rowIndices[k]; + for (var j = 0; j < ColumnCount; j++) + { + At(row, j, Zero); + } + } + } + + public virtual void ClearColumns(int[] columnIndices) + { + for (var k = 0; k < ColumnCount; k++) + { + int column = columnIndices[k]; + for (var i = 0; i < RowCount; i++) + { + At(i, column, Zero); + } + } + } + /// /// Indicates whether the current object is equal to another object of the same type. /// diff --git a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs index c92bd566..00727315 100644 --- a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Policy; using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Storage @@ -232,7 +233,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage /// WARNING: This method is not thread safe. Use "lock" with it and be sure to avoid deadlocks public int FindItem(int row, int column) { - // Determin bounds in columnIndices array where this item should be searched (using rowIndex) + // Determine bounds in columnIndices array where this item should be searched (using rowIndex) return Array.BinarySearch(ColumnIndices, RowPointers[row], RowPointers[row + 1] - RowPointers[row], column); } @@ -264,6 +265,12 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } public void Normalize() + { + NormalizeOrdering(); + NormalizeZeros(); + } + + public void NormalizeOrdering() { for (int i = 0; i < RowCount; i++) { @@ -274,6 +281,10 @@ namespace MathNet.Numerics.LinearAlgebra.Storage Sorting.Sort(ColumnIndices, Values, index, count); } } + } + + public void NormalizeZeros() + { MapInplace(x => x, Zeros.AllowSkip); } @@ -336,6 +347,26 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + public override void ClearRows(int[] rowIndices) + { + var rows = new bool[RowCount]; + for (int i = 0; i < rowIndices.Length; i++) + { + rows[rowIndices[i]] = true; + } + MapIndexedInplace((i, j, x) => rows[i] ? Zero : x, Zeros.AllowSkip); + } + + public override void ClearColumns(int[] columnIndices) + { + var columns = new bool[ColumnCount]; + for (int i = 0; i < columnIndices.Length; i++) + { + columns[columnIndices[i]] = true; + } + MapIndexedInplace((i, j, x) => columns[j] ? Zero : x, Zeros.AllowSkip); + } + /// /// Indicates whether the current object is equal to another object of the same type. /// diff --git a/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs b/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs index b9949817..35536153 100644 --- a/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs +++ b/src/UnitTests/LinearAlgebraTests/MatrixStructureTheory.cs @@ -148,17 +148,39 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests [Theory] public void CanClearSubMatrix(Matrix matrix) { - var cleared = matrix.Clone(); - Assume.That(cleared.RowCount, Is.GreaterThanOrEqualTo(2)); - Assume.That(cleared.ColumnCount, Is.GreaterThanOrEqualTo(2)); + Assume.That(matrix.RowCount, Is.GreaterThanOrEqualTo(2)); + Assume.That(matrix.ColumnCount, Is.GreaterThanOrEqualTo(2)); - cleared.Storage.Clear(0, 2, 1, 1); + var cleared = matrix.Clone(); + cleared.ClearSubMatrix(0, 2, 1, 1); Assert.That(cleared.At(0, 0), Is.EqualTo(matrix.At(0, 0))); Assert.That(cleared.At(1, 0), Is.EqualTo(matrix.At(1, 0))); Assert.That(cleared.At(0, 1), Is.EqualTo(Zero)); Assert.That(cleared.At(1, 1), Is.EqualTo(Zero)); } + [Theory] + public void CanClearRows(Matrix matrix) + { + Assume.That(matrix.RowCount, Is.GreaterThanOrEqualTo(2)); + + var cleared = matrix.Clone(); + cleared.ClearRows(1); + Assert.That(cleared.At(0, 0), Is.EqualTo(matrix.At(0, 0))); + Assert.That(cleared.At(1, 0), Is.EqualTo(Zero)); + } + + [Theory] + public void CanClearColumns(Matrix matrix) + { + Assume.That(matrix.ColumnCount, Is.GreaterThanOrEqualTo(2)); + + var cleared = matrix.Clone(); + cleared.ClearColumns(1); + Assert.That(cleared.At(0, 0), Is.EqualTo(matrix.At(0, 0))); + Assert.That(cleared.At(0, 1), Is.EqualTo(Zero)); + } + [Theory] public void CanToArray(Matrix matrix) {