From 12194f2a638895c42d0011e1a156ef8ce0311eec Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sat, 23 Feb 2013 15:43:00 +0100 Subject: [PATCH] LA: Migrate Matrix SetColumn/Row to storage routines --- src/Numerics/LinearAlgebra/Generic/Matrix.cs | 72 ++----------- .../Storage/DenseColumnMajorMatrixStorage.cs | 56 ++++++++-- .../Storage/DiagonalMatrixStorage.cs | 6 ++ .../Storage/MatrixStorage.Validation.cs | 26 +++++ .../LinearAlgebra/Storage/MatrixStorage.cs | 100 +++++++++++++++++- .../SparseCompressedRowMatrixStorage.cs | 4 + 6 files changed, 189 insertions(+), 75 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Generic/Matrix.cs b/src/Numerics/LinearAlgebra/Generic/Matrix.cs index c427bec3..e948003e 100644 --- a/src/Numerics/LinearAlgebra/Generic/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Generic/Matrix.cs @@ -385,7 +385,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic throw new ArgumentNullException("result"); } - Storage.CopySubRowTo(result.Storage, index, 0, 0, ColumnCount); + Storage.CopyRowTo(result.Storage, index); } /// @@ -470,7 +470,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic throw new ArgumentNullException("result"); } - Storage.CopySubColumnTo(result.Storage, index, 0, 0, RowCount); + Storage.CopyColumnTo(result.Storage, index); } /// @@ -804,27 +804,14 @@ namespace MathNet.Numerics.LinearAlgebra.Generic /// equal the number of rows of this Matrix. /// If the size of does not /// equal the number of rows of this Matrix. - public virtual void SetColumn(int columnIndex, T[] column) + public void SetColumn(int columnIndex, T[] column) { - if (columnIndex < 0 || columnIndex >= ColumnCount) - { - throw new ArgumentOutOfRangeException("columnIndex"); - } - if (column == null) { throw new ArgumentNullException("column"); } - if (column.Length != RowCount) - { - throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "column"); - } - - for (var i = 0; i < RowCount; i++) - { - At(i, columnIndex, column[i]); - } + Storage.CopyColumnFrom(new DenseVectorStorage(column.Length, column), columnIndex); } /// @@ -837,27 +824,14 @@ namespace MathNet.Numerics.LinearAlgebra.Generic /// or greater than or equal to the number of columns. /// If the size of does not /// equal the number of rows of this Matrix. - public virtual void SetColumn(int columnIndex, Vector column) + public void SetColumn(int columnIndex, Vector column) { - if (columnIndex < 0 || columnIndex >= ColumnCount) - { - throw new ArgumentOutOfRangeException("columnIndex"); - } - if (column == null) { throw new ArgumentNullException("column"); } - if (column.Count != RowCount) - { - throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "column"); - } - - for (var i = 0; i < RowCount; i++) - { - At(i, columnIndex, column[i]); - } + Storage.CopyColumnFrom(column.Storage, columnIndex); } /// @@ -913,27 +887,14 @@ namespace MathNet.Numerics.LinearAlgebra.Generic /// or greater than or equal to the number of rows. /// If the size of does not /// equal the number of columns of this Matrix. - public virtual void SetRow(int rowIndex, Vector row) + public void SetRow(int rowIndex, Vector row) { - if (rowIndex < 0 || rowIndex >= RowCount) - { - throw new ArgumentOutOfRangeException("rowIndex"); - } - if (row == null) { throw new ArgumentNullException("row"); } - if (row.Count != ColumnCount) - { - throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "row"); - } - - for (var i = 0; i < ColumnCount; i++) - { - At(rowIndex, i, row[i]); - } + Storage.CopyRowFrom(row.Storage, rowIndex); } /// @@ -946,27 +907,14 @@ namespace MathNet.Numerics.LinearAlgebra.Generic /// or greater than or equal to the number of rows. /// If the size of does not /// equal the number of columns of this Matrix. - public virtual void SetRow(int rowIndex, T[] row) + public void SetRow(int rowIndex, T[] row) { - if (rowIndex < 0 || rowIndex >= RowCount) - { - throw new ArgumentOutOfRangeException("rowIndex"); - } - if (row == null) { throw new ArgumentNullException("row"); } - if (row.Length != ColumnCount) - { - throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "row"); - } - - for (var i = 0; i < ColumnCount; i++) - { - At(rowIndex, i, row[i]); - } + Storage.CopyRowFrom(new DenseVectorStorage(row.Length, row), rowIndex); } /// diff --git a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs index fa940cd6..151cfe3c 100644 --- a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs @@ -122,12 +122,17 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // ROW COPY + internal override void CopySubRowToUnchecked(VectorStorage target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) { - var denseTarget = target as DenseVectorStorage; - if (denseTarget != null) + var targetDense = target as DenseVectorStorage; + if (targetDense != null) { - CopySubRowToUnchecked(denseTarget, rowIndex, sourceColumnIndex, targetColumnIndex, columnCount); + for (int j = 0; j target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) + internal override void CopySubRowFromUnchecked(VectorStorage source, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) { - for (int j = 0; j; + if (sourceDense != null) + { + for (int j = 0; j < columnCount; j++) + { + Data[(j + targetColumnIndex) * RowCount + rowIndex] = sourceDense.Data[j + sourceColumnIndex]; + } + return; + } + + // FALL BACK + + for (int j = sourceColumnIndex, jj = targetColumnIndex; j < sourceColumnIndex + columnCount; j++, jj++) { - target.Data[j + targetColumnIndex] = Data[(j + sourceColumnIndex) * RowCount + rowIndex]; + Data[(jj * RowCount) + rowIndex] = source.At(j); } } + // COLUMN COPY + internal override void CopySubColumnToUnchecked(VectorStorage target, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) { - var denseTarget = target as DenseVectorStorage; - if (denseTarget != null) + var targetDense = target as DenseVectorStorage; + if (targetDense != null) { - CopySubColumnToUnchecked(denseTarget, columnIndex, sourceRowIndex, targetRowIndex, rowCount); + Array.Copy(Data, columnIndex*RowCount + sourceRowIndex, targetDense.Data, targetRowIndex, rowCount); return; } @@ -165,11 +184,26 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } - void CopySubColumnToUnchecked(DenseVectorStorage target, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) + internal override void CopySubColumnFromUnchecked(VectorStorage source, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) { - Array.Copy(Data, columnIndex*RowCount + sourceRowIndex, target.Data, targetRowIndex, rowCount); + var sourceDense = source as DenseVectorStorage; + if (sourceDense != null) + { + Array.Copy(sourceDense.Data, sourceRowIndex, Data, columnIndex * RowCount + targetRowIndex, rowCount); + return; + } + + // FALL BACK + + var offset = columnIndex * RowCount; + for (int i = sourceRowIndex, ii = targetRowIndex; i < sourceRowIndex + rowCount; i++, ii++) + { + Data[offset + ii] = source.At(i); + } } + // EXTRACT + public override T[] ToRowMajorArray() { var ret = new T[Data.Length]; diff --git a/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs index a08775a3..387916c3 100644 --- a/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs @@ -356,6 +356,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage // else: all zero, nop } + // ROW COPY + internal override void CopySubRowToUnchecked(VectorStorage target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) @@ -371,6 +373,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // COLUMN COPY + internal override void CopySubColumnToUnchecked(VectorStorage target, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) @@ -386,6 +390,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // EXTRACT + public override T[] ToRowMajorArray() { var ret = new T[RowCount * ColumnCount]; diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.Validation.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.Validation.cs index 437e7753..73520307 100644 --- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.Validation.cs +++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.Validation.cs @@ -84,6 +84,32 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + void ValidateRowRange(VectorStorage target, int rowIndex) + { + if (rowIndex >= RowCount || rowIndex < 0) + { + throw new ArgumentOutOfRangeException("rowIndex"); + } + + if (ColumnCount != target.Length) + { + throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "target"); + } + } + + void ValidateColumnRange(VectorStorage target, int columnIndex) + { + if (columnIndex >= ColumnCount || columnIndex < 0) + { + throw new ArgumentOutOfRangeException("columnIndex"); + } + + if (RowCount != target.Length) + { + throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "target"); + } + } + void ValidateSubRowRange(VectorStorage target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount) { diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs index 1237fcd6..979ffb94 100644 --- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs @@ -195,6 +195,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return hash; } + // MATRIX COPY + public void CopyTo(MatrixStorage target, bool skipClearing = false) { if (target == null) @@ -264,6 +266,19 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // ROW COPY + + public void CopyRowTo(VectorStorage target, int rowIndex, bool skipClearing = false) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + ValidateRowRange(target, rowIndex); + CopySubRowToUnchecked(target, rowIndex, 0, 0, ColumnCount, skipClearing); + } + public void CopySubRowTo(VectorStorage target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) @@ -274,7 +289,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } ValidateSubRowRange(target, rowIndex, sourceColumnIndex, targetColumnIndex, columnCount); - CopySubRowToUnchecked(target, rowIndex, sourceColumnIndex, targetColumnIndex, columnCount, skipClearing); } @@ -288,6 +302,53 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + public void CopyRowFrom(VectorStorage source, int rowIndex, bool skipClearing = false) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + ValidateRowRange(source, rowIndex); + CopySubRowFromUnchecked(source, rowIndex, 0, 0, ColumnCount, skipClearing); + } + + public void CopySubRowFrom(VectorStorage source, int rowIndex, + int sourceColumnIndex, int targetColumnIndex, int columnCount, + bool skipClearing = false) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + ValidateSubRowRange(source, rowIndex, targetColumnIndex, sourceColumnIndex, columnCount); + CopySubRowFromUnchecked(source, rowIndex, sourceColumnIndex, targetColumnIndex, columnCount, skipClearing); + } + + internal virtual void CopySubRowFromUnchecked(VectorStorage source, int rowIndex, + int sourceColumnIndex, int targetColumnIndex, int columnCount, + bool skipClearing = false) + { + for (int j = sourceColumnIndex, jj = targetColumnIndex; j < sourceColumnIndex + columnCount; j++, jj++) + { + At(rowIndex, jj, source.At(j)); + } + } + + // COLUMN COPY + + public void CopyColumnTo(VectorStorage target, int columnIndex, bool skipClearing = false) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + ValidateColumnRange(target, columnIndex); + CopySubColumnToUnchecked(target, columnIndex, 0, 0, RowCount, skipClearing); + } + public void CopySubColumnTo(VectorStorage target, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) @@ -298,7 +359,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } ValidateSubColumnRange(target, columnIndex, sourceRowIndex, targetRowIndex, rowCount); - CopySubColumnToUnchecked(target, columnIndex, sourceRowIndex, targetRowIndex, rowCount, skipClearing); } @@ -312,6 +372,42 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + public void CopyColumnFrom(VectorStorage source, int columnIndex, bool skipClearing = false) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + ValidateColumnRange(source, columnIndex); + CopySubColumnFromUnchecked(source, columnIndex, 0, 0, RowCount, skipClearing); + } + + public void CopySubColumnFrom(VectorStorage source, int columnIndex, + int sourceRowIndex, int targetRowIndex, int rowCount, + bool skipClearing = false) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + ValidateSubColumnRange(source, columnIndex, targetRowIndex, sourceRowIndex, rowCount); + CopySubColumnFromUnchecked(source, columnIndex, sourceRowIndex, targetRowIndex, rowCount, skipClearing); + } + + internal virtual void CopySubColumnFromUnchecked(VectorStorage source, int columnIndex, + int sourceRowIndex, int targetRowIndex, int rowCount, + bool skipClearing = false) + { + for (int i = sourceRowIndex, ii = targetRowIndex; i < sourceRowIndex + rowCount; i++, ii++) + { + At(ii, columnIndex, source.At(i)); + } + } + + // EXTRACT + public virtual T[] ToRowMajorArray() { var ret = new T[RowCount * ColumnCount]; diff --git a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs index aa6627b7..cf9d209f 100644 --- a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs @@ -525,6 +525,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // ROW COPY + internal override void CopySubRowToUnchecked(VectorStorage target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) @@ -551,6 +553,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // EXTRACT + public override T[] ToRowMajorArray() { var ret = new T[RowCount * ColumnCount];