From 2654f4b481746763f0c084ee4e726a8ca316cd58 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 24 Feb 2013 20:43:34 +0100 Subject: [PATCH] LA: Storage always provide CopyTo, never CopyFrom --- src/Numerics/LinearAlgebra/Generic/Matrix.cs | 24 ++-- src/Numerics/LinearAlgebra/Generic/Vector.cs | 4 +- .../Storage/DenseColumnMajorMatrixStorage.cs | 38 ------- .../Storage/DenseVectorStorage.cs | 95 ++++++++++++++-- .../LinearAlgebra/Storage/MatrixStorage.cs | 68 ----------- .../Storage/SparseVectorStorage.cs | 4 + .../Storage/VectorStorage.Validation.cs | 106 ++++++++++++++++- .../LinearAlgebra/Storage/VectorStorage.cs | 107 +++++++++++++++++- 8 files changed, 314 insertions(+), 132 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Generic/Matrix.cs b/src/Numerics/LinearAlgebra/Generic/Matrix.cs index aae27d2b..94c0bd6f 100644 --- a/src/Numerics/LinearAlgebra/Generic/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Generic/Matrix.cs @@ -798,45 +798,45 @@ namespace MathNet.Numerics.LinearAlgebra.Generic } /// - /// Copies the values of the given array to the specified column. + /// Copies the values of the given Vector to the specified column. /// /// The column to copy the values to. - /// The array to copy the values from. + /// The vector to copy the values from. /// If is . /// If is less than zero, /// or greater than or equal to the number of columns. /// If the size of does not /// equal the number of rows of this Matrix. - /// If the size of does not - /// equal the number of rows of this Matrix. - public void SetColumn(int columnIndex, T[] column) + public void SetColumn(int columnIndex, Vector column) { if (column == null) { throw new ArgumentNullException("column"); } - Storage.CopyColumnFrom(new DenseVectorStorage(column.Length, column), columnIndex); + column.Storage.CopyToColumn(Storage, columnIndex); } /// - /// Copies the values of the given Vector to the specified column. + /// Copies the values of the given array to the specified column. /// /// The column to copy the values to. - /// The vector to copy the values from. + /// The array to copy the values from. /// If is . /// If is less than zero, /// 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 void SetColumn(int columnIndex, Vector column) + /// If the size of does not + /// equal the number of rows of this Matrix. + public void SetColumn(int columnIndex, T[] column) { if (column == null) { throw new ArgumentNullException("column"); } - Storage.CopyColumnFrom(column.Storage, columnIndex); + new DenseVectorStorage(column.Length, column).CopyToColumn(Storage, columnIndex); } /// @@ -899,7 +899,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic throw new ArgumentNullException("row"); } - Storage.CopyRowFrom(row.Storage, rowIndex); + row.Storage.CopyToRow(Storage, rowIndex); } /// @@ -919,7 +919,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic throw new ArgumentNullException("row"); } - Storage.CopyRowFrom(new DenseVectorStorage(row.Length, row), rowIndex); + new DenseVectorStorage(row.Length, row).CopyToRow(Storage, rowIndex); } /// diff --git a/src/Numerics/LinearAlgebra/Generic/Vector.cs b/src/Numerics/LinearAlgebra/Generic/Vector.cs index dbd27fb3..ff1f8088 100644 --- a/src/Numerics/LinearAlgebra/Generic/Vector.cs +++ b/src/Numerics/LinearAlgebra/Generic/Vector.cs @@ -1176,7 +1176,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic public virtual Matrix ToColumnMatrix() { var result = CreateMatrix(Count, 1); - result.Storage.CopyColumnFrom(Storage, 0, skipClearing: true); + Storage.CopyToColumnUnchecked(result.Storage, 0, skipClearing: true); return result; } @@ -1189,7 +1189,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic public virtual Matrix ToRowMatrix() { var result = CreateMatrix(1, Count); - result.Storage.CopyRowFrom(Storage, 0, skipClearing: true); + Storage.CopyToRowUnchecked(result.Storage, 0, skipClearing: true); return result; } diff --git a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs index 5729d9cd..90937964 100644 --- a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs @@ -174,26 +174,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } - internal override void CopySubRowFromUnchecked(VectorStorage source, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) - { - var sourceDense = source as DenseVectorStorage; - 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++) - { - 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) @@ -214,24 +194,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } - internal override void CopySubColumnFromUnchecked(VectorStorage source, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) - { - 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() diff --git a/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs index 896991b2..822a49f3 100644 --- a/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs @@ -89,33 +89,71 @@ namespace MathNet.Numerics.LinearAlgebra.Storage Array.Clear(Data, index, count); } + // VECTOR COPY + internal override void CopyToUnchecked(VectorStorage target, bool skipClearing = false) { var denseTarget = target as DenseVectorStorage; if (denseTarget != null) { - CopyToUnchecked(denseTarget); + if (!ReferenceEquals(this, denseTarget)) + { + Array.Copy(Data, 0, denseTarget.Data, 0, Data.Length); + } return; } // FALL BACK - for (int i = 0; i < Length; i++) + for (int i = 0; i < Data.Length; i++) { target.At(i, Data[i]); } } - void CopyToUnchecked(DenseVectorStorage target) + // ROW COPY + + internal override void CopyToRowUnchecked(MatrixStorage target, int rowIndex, bool skipClearing = false) + { + var denseTarget = target as DenseColumnMajorMatrixStorage; + if (denseTarget != null) + { + for (int j = 0; j < Data.Length; j++) + { + denseTarget.Data[j*target.RowCount + rowIndex] = Data[j]; + } + return; + } + + // FALL BACK + + for (int j = 0; j < Length; j++) + { + target.At(rowIndex, j, Data[j]); + } + } + + // COLUMN COPY + + internal override void CopyToColumnUnchecked(MatrixStorage target, int columnIndex, bool skipClearing = false) { - if (ReferenceEquals(this, target)) + var denseTarget = target as DenseColumnMajorMatrixStorage; + if (denseTarget != null) { + Array.Copy(Data, 0, denseTarget.Data, columnIndex * denseTarget.RowCount, Data.Length); return; } - Array.Copy(Data, 0, target.Data, 0, Data.Length); + // FALL BACK + + for (int i = 0; i < Length; i++) + { + target.At(i, columnIndex, Data[i]); + } } + // SUB-VECTOR COPY + internal override void CopySubVectorToUnchecked(VectorStorage target, int sourceIndex, int targetIndex, int count, bool skipClearing = false) @@ -123,7 +161,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage var denseTarget = target as DenseVectorStorage; if (denseTarget != null) { - CopySubVectorToUnchecked(denseTarget, sourceIndex, targetIndex, count); + Array.Copy(Data, sourceIndex, denseTarget.Data, targetIndex, count); return; } @@ -132,10 +170,49 @@ namespace MathNet.Numerics.LinearAlgebra.Storage base.CopySubVectorToUnchecked(target, sourceIndex, targetIndex, count, skipClearing); } - void CopySubVectorToUnchecked(DenseVectorStorage target, - int sourceIndex, int targetIndex, int count) + // SUB-ROW COPY + + internal override void CopyToSubRowUnchecked(MatrixStorage target, int rowIndex, + int sourceColumnIndex, int targetColumnIndex, int columnCount, + bool skipClearing = false) + { + var denseTarget = target as DenseColumnMajorMatrixStorage; + if (denseTarget != null) + { + for (int j = 0; j < Data.Length; j++) + { + denseTarget.Data[(j + targetColumnIndex) * target.RowCount + rowIndex] = Data[j + sourceColumnIndex]; + } + return; + } + + // FALL BACK + + for (int j = sourceColumnIndex, jj = targetColumnIndex; j < sourceColumnIndex + columnCount; j++, jj++) + { + target.At(rowIndex, jj, Data[j]); + } + } + + // SUB-COLUMN COPY + + internal override void CopyToSubColumnUnchecked(MatrixStorage target, int columnIndex, + int sourceRowIndex, int targetRowIndex, int rowCount, + bool skipClearing = false) { - Array.Copy(Data, sourceIndex, target.Data, targetIndex, count); + var denseTarget = target as DenseColumnMajorMatrixStorage; + if (denseTarget != null) + { + Array.Copy(Data, sourceRowIndex, denseTarget.Data, columnIndex*denseTarget.RowCount + targetRowIndex, rowCount); + return; + } + + // FALL BACK + + for (int i = sourceRowIndex, ii = targetRowIndex; i < sourceRowIndex + rowCount; i++, ii++) + { + target.At(ii, columnIndex, Data[i]); + } } } } diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs index f6ed538a..9d586e35 100644 --- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs @@ -332,40 +332,6 @@ 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) @@ -402,40 +368,6 @@ 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() diff --git a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs index ec4e843c..1094ba7b 100644 --- a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs @@ -284,6 +284,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return hash; } + // VECTOR COPY + internal override void CopyToUnchecked(VectorStorage target, bool skipClearing = false) { var sparseTarget = target as SparseVectorStorage; @@ -333,6 +335,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // SUB-VECTOR COPY + internal override void CopySubVectorToUnchecked(VectorStorage target, int sourceIndex, int targetIndex, int count, bool skipClearing = false) diff --git a/src/Numerics/LinearAlgebra/Storage/VectorStorage.Validation.cs b/src/Numerics/LinearAlgebra/Storage/VectorStorage.Validation.cs index 325920fa..a4588737 100644 --- a/src/Numerics/LinearAlgebra/Storage/VectorStorage.Validation.cs +++ b/src/Numerics/LinearAlgebra/Storage/VectorStorage.Validation.cs @@ -36,7 +36,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage // ReSharper disable UnusedParameter.Global public partial class VectorStorage { - protected void ValidateRange(int index) + void ValidateRange(int index) { if (index < 0 || index >= Length) { @@ -44,7 +44,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } - protected void ValidateSubVectorRange(VectorStorage target, + void ValidateSubVectorRange(VectorStorage target, int sourceIndex, int targetIndex, int count) { if (count < 1) @@ -80,6 +80,108 @@ namespace MathNet.Numerics.LinearAlgebra.Storage throw new ArgumentOutOfRangeException("count"); } } + + void ValidateRowRange(MatrixStorage target, int rowIndex) + { + if (rowIndex >= target.RowCount || rowIndex < 0) + { + throw new ArgumentOutOfRangeException("rowIndex"); + } + + if (target.ColumnCount != Length) + { + throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "target"); + } + } + + void ValidateColumnRange(MatrixStorage target, int columnIndex) + { + if (columnIndex >= target.ColumnCount || columnIndex < 0) + { + throw new ArgumentOutOfRangeException("columnIndex"); + } + + if (target.RowCount != Length) + { + throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "target"); + } + } + + void ValidateSubRowRange(MatrixStorage target, int rowIndex, + int sourceColumnIndex, int targetColumnIndex, int columnCount) + { + if (columnCount < 1) + { + throw new ArgumentOutOfRangeException("columnCount", Resources.ArgumentMustBePositive); + } + + // Verify Source + + if (sourceColumnIndex >= Length || sourceColumnIndex < 0) + { + throw new ArgumentOutOfRangeException("sourceColumnIndex"); + } + + if (sourceColumnIndex + columnCount > Length) + { + throw new ArgumentOutOfRangeException("columnCount"); + } + + // Verify Target + + if (rowIndex >= target.RowCount || rowIndex < 0) + { + throw new ArgumentOutOfRangeException("rowIndex"); + } + + if (targetColumnIndex >= target.ColumnCount || targetColumnIndex < 0) + { + throw new ArgumentOutOfRangeException("targetColumnIndex"); + } + + if (targetColumnIndex + columnCount > target.ColumnCount) + { + throw new ArgumentOutOfRangeException("columnCount"); + } + } + + void ValidateSubColumnRange(MatrixStorage target, int columnIndex, + int sourceRowIndex, int targetRowIndex, int rowCount) + { + if (rowCount < 1) + { + throw new ArgumentOutOfRangeException("rowCount", Resources.ArgumentMustBePositive); + } + + // Verify Source + + if (sourceRowIndex >= Length || sourceRowIndex < 0) + { + throw new ArgumentOutOfRangeException("sourceRowIndex"); + } + + if (sourceRowIndex + rowCount > Length) + { + throw new ArgumentOutOfRangeException("rowCount"); + } + + // Verify Target + + if (columnIndex >= target.ColumnCount || columnIndex < 0) + { + throw new ArgumentOutOfRangeException("columnIndex"); + } + + if (targetRowIndex >= target.RowCount || targetRowIndex < 0) + { + throw new ArgumentOutOfRangeException("targetRowIndex"); + } + + if (targetRowIndex + rowCount > target.RowCount) + { + throw new ArgumentOutOfRangeException("rowCount"); + } + } } // ReSharper restore UnusedParameter.Global } diff --git a/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs index 8883512e..1bb76f45 100644 --- a/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs @@ -196,6 +196,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return hash; } + // VECTOR COPY + public void CopyTo(VectorStorage target, bool skipClearing = false) { if (target == null) @@ -224,6 +226,60 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } } + // ROW COPY + + public void CopyToRow(MatrixStorage target, int rowIndex, bool skipClearing = false) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + if (Length != target.ColumnCount) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target"); + } + + ValidateRowRange(target, rowIndex); + CopyToRowUnchecked(target, rowIndex, skipClearing); + } + + internal virtual void CopyToRowUnchecked(MatrixStorage target, int rowIndex, bool skipClearing = false) + { + for (int j = 0; j < Length; j++) + { + target.At(rowIndex, j, At(j)); + } + } + + // COLUMN COPY + + public void CopyToColumn(MatrixStorage target, int columnIndex, bool skipClearing = false) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + if (Length != target.RowCount) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target"); + } + + ValidateColumnRange(target, columnIndex); + CopyToColumnUnchecked(target, columnIndex, skipClearing); + } + + internal virtual void CopyToColumnUnchecked(MatrixStorage target, int columnIndex, bool skipClearing = false) + { + for (int i = 0; i < Length; i++) + { + target.At(i, columnIndex, At(i)); + } + } + + // SUB-VECTOR COPY + public void CopySubVectorTo(VectorStorage target, int sourceIndex, int targetIndex, int count, bool skipClearing = false) @@ -234,7 +290,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } ValidateSubVectorRange(target, sourceIndex, targetIndex, count); - CopySubVectorToUnchecked(target, sourceIndex, targetIndex, count, skipClearing); } @@ -262,5 +317,55 @@ namespace MathNet.Numerics.LinearAlgebra.Storage target.At(ii, At(i)); } } + + // SUB-ROW COPY + + public void CopyToSubRow(MatrixStorage target, int rowIndex, + int sourceColumnIndex, int targetColumnIndex, int columnCount, + bool skipClearing = false) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + ValidateSubRowRange(target, rowIndex, targetColumnIndex, sourceColumnIndex, columnCount); + CopyToSubRowUnchecked(target, rowIndex, sourceColumnIndex, targetColumnIndex, columnCount, skipClearing); + } + + internal virtual void CopyToSubRowUnchecked(MatrixStorage target, int rowIndex, + int sourceColumnIndex, int targetColumnIndex, int columnCount, + bool skipClearing = false) + { + for (int j = sourceColumnIndex, jj = targetColumnIndex; j < sourceColumnIndex + columnCount; j++, jj++) + { + target.At(rowIndex, jj, At(j)); + } + } + + // SUB-COLUMN COPY + + public void CopyToSubColumn(MatrixStorage target, int columnIndex, + int sourceRowIndex, int targetRowIndex, int rowCount, + bool skipClearing = false) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + ValidateSubColumnRange(target, columnIndex, sourceRowIndex, targetRowIndex, rowCount); + CopyToSubColumnUnchecked(target, columnIndex, sourceRowIndex, targetRowIndex, rowCount, skipClearing); + } + + internal virtual void CopyToSubColumnUnchecked(MatrixStorage target, int columnIndex, + int sourceRowIndex, int targetRowIndex, int rowCount, + bool skipClearing = false) + { + for (int i = sourceRowIndex, ii = targetRowIndex; i < sourceRowIndex + rowCount; i++, ii++) + { + target.At(ii, columnIndex, At(i)); + } + } } }