From 16414ce904636bd2fe5020cdaba352642918f66b Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sat, 14 Jul 2012 15:31:09 +0200 Subject: [PATCH] Perf: override CopyTo for all linear algebra types --- .../LinearAlgebra/Complex/DenseMatrix.cs | 34 +++++++++++++++ .../LinearAlgebra/Complex/DenseVector.cs | 43 +++++++++++++++++++ .../LinearAlgebra/Complex/SparseMatrix.cs | 33 +++++++------- .../LinearAlgebra/Complex/SparseVector.cs | 2 +- .../LinearAlgebra/Complex32/DenseMatrix.cs | 34 +++++++++++++++ .../LinearAlgebra/Complex32/DenseVector.cs | 43 +++++++++++++++++++ .../LinearAlgebra/Complex32/SparseMatrix.cs | 33 +++++++------- .../LinearAlgebra/Complex32/SparseVector.cs | 2 +- .../LinearAlgebra/Double/DenseMatrix.cs | 34 +++++++++++++++ .../LinearAlgebra/Double/SparseMatrix.cs | 35 +++++++-------- .../LinearAlgebra/Double/SparseVector.cs | 7 ++- src/Numerics/LinearAlgebra/Generic/Matrix.cs | 23 +++++----- .../LinearAlgebra/Single/DenseMatrix.cs | 34 +++++++++++++++ .../LinearAlgebra/Single/SparseMatrix.cs | 35 +++++++-------- .../LinearAlgebra/Single/SparseVector.cs | 7 ++- 15 files changed, 317 insertions(+), 82 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs index 2311f42b..60015996 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs @@ -180,6 +180,40 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new DenseVector(size); } + /// + /// Copies the elements of this matrix to the given matrix. + /// + /// + /// The matrix to copy values into. + /// + /// + /// If target is . + /// + /// + /// If this and the target matrix do not have the same dimensions.. + /// + public override void CopyTo(Matrix target) + { + var denseTarget = target as DenseMatrix; + if (denseTarget == null) + { + base.CopyTo(target); + return; + } + + if (ReferenceEquals(this, target)) + { + return; + } + + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } + + Array.Copy(Data, 0, denseTarget.Data, 0, Data.Length); + } + /// /// Gets or sets the value at the given row and column. /// diff --git a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs index cd75ab8b..2053a6b3 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs @@ -244,6 +244,49 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new DenseVector(size); } + /// + /// Copies the values of this vector into the target vector. + /// + /// + /// The vector to copy elements into. + /// + /// + /// If is . + /// + /// + /// If is not the same size as this vector. + /// + public override void CopyTo(Vector target) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + if (Count != target.Count) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target"); + } + + if (ReferenceEquals(this, target)) + { + return; + } + + var otherVector = target as DenseVector; + if (otherVector == null) + { + CommonParallel.For( + 0, + Data.Length, + index => target[index] = Data[index]); + } + else + { + Array.Copy(Data, 0, otherVector.Data, 0, Data.Length); + } + } + /// /// Adds a scalar to each element of the vector and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs index d76968a2..0717522e 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs @@ -803,31 +803,32 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public override void CopyTo(Matrix target) { var sparseTarget = target as SparseMatrix; - if (sparseTarget == null) { base.CopyTo(target); + return; } - else + + if (ReferenceEquals(this, target)) { - if (ReferenceEquals(this, target)) - { - return; - } + return; + } - if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) - { - throw DimensionsDontMatch(this, target, "target"); - } + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } - // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value - sparseTarget._nonZeroValues = new Complex[NonZerosCount]; - sparseTarget._columnIndices = new int[NonZerosCount]; - sparseTarget.NonZerosCount = NonZerosCount; + // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value + sparseTarget._nonZeroValues = new Complex[NonZerosCount]; + sparseTarget._columnIndices = new int[NonZerosCount]; + sparseTarget.NonZerosCount = NonZerosCount; + if (NonZerosCount != 0) + { Array.Copy(_nonZeroValues, sparseTarget._nonZeroValues, NonZerosCount); - Array.Copy(_columnIndices, sparseTarget._columnIndices, NonZerosCount); - Array.Copy(_rowIndex, sparseTarget._rowIndex, RowCount); + Buffer.BlockCopy(_columnIndices, 0, sparseTarget._columnIndices, 0, NonZerosCount * Constants.SizeOfInt); + Buffer.BlockCopy(_rowIndex, 0, sparseTarget._rowIndex, 0, RowCount * Constants.SizeOfInt); } } diff --git a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs index 353b21a7..318bacd9 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs @@ -304,7 +304,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex if (NonZerosCount != 0) { - CommonParallel.For(0, NonZerosCount, index => otherVector._nonZeroValues[index] = _nonZeroValues[index]); + Array.Copy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount); Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt); } } diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs index 4ee493cd..a19dc67a 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs @@ -180,6 +180,40 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new DenseVector(size); } + /// + /// Copies the elements of this matrix to the given matrix. + /// + /// + /// The matrix to copy values into. + /// + /// + /// If target is . + /// + /// + /// If this and the target matrix do not have the same dimensions.. + /// + public override void CopyTo(Matrix target) + { + var denseTarget = target as DenseMatrix; + if (denseTarget == null) + { + base.CopyTo(target); + return; + } + + if (ReferenceEquals(this, target)) + { + return; + } + + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } + + Array.Copy(Data, 0, denseTarget.Data, 0, Data.Length); + } + /// /// Gets or sets the value at the given row and column. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs index 2d074053..2bb912bd 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs @@ -245,6 +245,49 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new DenseVector(size); } + /// + /// Copies the values of this vector into the target vector. + /// + /// + /// The vector to copy elements into. + /// + /// + /// If is . + /// + /// + /// If is not the same size as this vector. + /// + public override void CopyTo(Vector target) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + if (Count != target.Count) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target"); + } + + if (ReferenceEquals(this, target)) + { + return; + } + + var otherVector = target as DenseVector; + if (otherVector == null) + { + CommonParallel.For( + 0, + Data.Length, + index => target[index] = Data[index]); + } + else + { + Array.Copy(Data, 0, otherVector.Data, 0, Data.Length); + } + } + /// /// Adds a scalar to each element of the vector and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs index 11d9cfd6..8fd77e6f 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs @@ -804,31 +804,32 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public override void CopyTo(Matrix target) { var sparseTarget = target as SparseMatrix; - if (sparseTarget == null) { base.CopyTo(target); + return; } - else + + if (ReferenceEquals(this, target)) { - if (ReferenceEquals(this, target)) - { - return; - } + return; + } - if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) - { - throw DimensionsDontMatch(this, target, "target"); - } + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } - // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value - sparseTarget._nonZeroValues = new Complex32[NonZerosCount]; - sparseTarget._columnIndices = new int[NonZerosCount]; - sparseTarget.NonZerosCount = NonZerosCount; + // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value + sparseTarget._nonZeroValues = new Complex32[NonZerosCount]; + sparseTarget._columnIndices = new int[NonZerosCount]; + sparseTarget.NonZerosCount = NonZerosCount; + if (NonZerosCount != 0) + { Array.Copy(_nonZeroValues, sparseTarget._nonZeroValues, NonZerosCount); - Array.Copy(_columnIndices, sparseTarget._columnIndices, NonZerosCount); - Array.Copy(_rowIndex, sparseTarget._rowIndex, RowCount); + Buffer.BlockCopy(_columnIndices, 0, sparseTarget._columnIndices, 0, NonZerosCount * Constants.SizeOfInt); + Buffer.BlockCopy(_rowIndex, 0, sparseTarget._rowIndex, 0, RowCount * Constants.SizeOfInt); } } diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs index 3548e7b3..753dc646 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs @@ -334,7 +334,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 if (NonZerosCount != 0) { - CommonParallel.For(0, NonZerosCount, index => otherVector._nonZeroValues[index] = _nonZeroValues[index]); + Array.Copy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount); Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt); } } diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs index daeaae36..4697f324 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs @@ -181,6 +181,40 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new DenseVector(size); } + /// + /// Copies the elements of this matrix to the given matrix. + /// + /// + /// The matrix to copy values into. + /// + /// + /// If target is . + /// + /// + /// If this and the target matrix do not have the same dimensions.. + /// + public override void CopyTo(Matrix target) + { + var denseTarget = target as DenseMatrix; + if (denseTarget == null) + { + base.CopyTo(target); + return; + } + + if (ReferenceEquals(this, target)) + { + return; + } + + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } + + Buffer.BlockCopy(Data, 0, denseTarget.Data, 0, Data.Length * Constants.SizeOfDouble); + } + /// /// Gets or sets the value at the given row and column. /// diff --git a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs index c43f6072..a2bae092 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs @@ -815,31 +815,32 @@ namespace MathNet.Numerics.LinearAlgebra.Double public override void CopyTo(Matrix target) { var sparseTarget = target as SparseMatrix; - if (sparseTarget == null) { base.CopyTo(target); + return; } - else + + if (ReferenceEquals(this, target)) { - if (ReferenceEquals(this, target)) - { - return; - } + return; + } - if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) - { - throw DimensionsDontMatch(this, target, "target"); - } + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } - // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value - sparseTarget._nonZeroValues = new double[NonZerosCount]; - sparseTarget._columnIndices = new int[NonZerosCount]; - sparseTarget.NonZerosCount = NonZerosCount; + // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value + sparseTarget._nonZeroValues = new double[NonZerosCount]; + sparseTarget._columnIndices = new int[NonZerosCount]; + sparseTarget.NonZerosCount = NonZerosCount; - Buffer.BlockCopy(_nonZeroValues, 0, sparseTarget._nonZeroValues, 0, NonZerosCount * Constants.SizeOfDouble); - Buffer.BlockCopy(_columnIndices, 0, sparseTarget._columnIndices, 0, NonZerosCount * Constants.SizeOfInt); - Buffer.BlockCopy(_rowIndex, 0, sparseTarget._rowIndex, 0, RowCount * Constants.SizeOfInt); + if (NonZerosCount != 0) + { + Buffer.BlockCopy(_nonZeroValues, 0, sparseTarget._nonZeroValues, 0, NonZerosCount*Constants.SizeOfDouble); + Buffer.BlockCopy(_columnIndices, 0, sparseTarget._columnIndices, 0, NonZerosCount*Constants.SizeOfInt); + Buffer.BlockCopy(_rowIndex, 0, sparseTarget._rowIndex, 0, RowCount*Constants.SizeOfInt); } } diff --git a/src/Numerics/LinearAlgebra/Double/SparseVector.cs b/src/Numerics/LinearAlgebra/Double/SparseVector.cs index 411da5cc..d0d62eda 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseVector.cs @@ -296,8 +296,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double otherVector._nonZeroIndices = new int[NonZerosCount]; otherVector.NonZerosCount = NonZerosCount; - Buffer.BlockCopy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount * Constants.SizeOfDouble); - Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt); + if (NonZerosCount != 0) + { + Buffer.BlockCopy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount*Constants.SizeOfDouble); + Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount*Constants.SizeOfInt); + } } } diff --git a/src/Numerics/LinearAlgebra/Generic/Matrix.cs b/src/Numerics/LinearAlgebra/Generic/Matrix.cs index 1c0ed835..8865bd22 100644 --- a/src/Numerics/LinearAlgebra/Generic/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Generic/Matrix.cs @@ -273,23 +273,26 @@ namespace MathNet.Numerics.LinearAlgebra.Generic throw new ArgumentNullException("target"); } - if (ReferenceEquals(this, target)) - { - return; - } - if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) { throw DimensionsDontMatch(this, target); } - for (var i = 0; i < RowCount; i++) + if (ReferenceEquals(this, target)) { - for (var j = 0; j < ColumnCount; j++) - { - target.At(i, j, At(i, j)); - } + return; } + + CommonParallel.For( + 0, + RowCount, + row => + { + for (var j = 0; j < ColumnCount; j++) + { + target.At(row, j, At(row, j)); + } + }); } /// diff --git a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs index 0d1dcbcd..494f69f1 100644 --- a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs @@ -180,6 +180,40 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new DenseVector(size); } + /// + /// Copies the elements of this matrix to the given matrix. + /// + /// + /// The matrix to copy values into. + /// + /// + /// If target is . + /// + /// + /// If this and the target matrix do not have the same dimensions.. + /// + public override void CopyTo(Matrix target) + { + var denseTarget = target as DenseMatrix; + if (denseTarget == null) + { + base.CopyTo(target); + return; + } + + if (ReferenceEquals(this, target)) + { + return; + } + + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } + + Buffer.BlockCopy(Data, 0, denseTarget.Data, 0, Data.Length * Constants.SizeOfFloat); + } + /// /// Gets or sets the value at the given row and column. /// diff --git a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs index 78d47de6..c1466146 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs @@ -798,31 +798,32 @@ namespace MathNet.Numerics.LinearAlgebra.Single public override void CopyTo(Matrix target) { var sparseTarget = target as SparseMatrix; - if (sparseTarget == null) { base.CopyTo(target); + return; } - else + + if (ReferenceEquals(this, target)) { - if (ReferenceEquals(this, target)) - { - return; - } + return; + } - if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) - { - throw DimensionsDontMatch(this, target, "target"); - } + if (RowCount != target.RowCount || ColumnCount != target.ColumnCount) + { + throw DimensionsDontMatch(this, target, "target"); + } - // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value - sparseTarget._nonZeroValues = new float[NonZerosCount]; - sparseTarget._columnIndices = new int[NonZerosCount]; - sparseTarget.NonZerosCount = NonZerosCount; + // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value + sparseTarget._nonZeroValues = new float[NonZerosCount]; + sparseTarget._columnIndices = new int[NonZerosCount]; + sparseTarget.NonZerosCount = NonZerosCount; - Buffer.BlockCopy(_nonZeroValues, 0, sparseTarget._nonZeroValues, 0, NonZerosCount * Constants.SizeOfFloat); - Buffer.BlockCopy(_columnIndices, 0, sparseTarget._columnIndices, 0, NonZerosCount * Constants.SizeOfInt); - Buffer.BlockCopy(_rowIndex, 0, sparseTarget._rowIndex, 0, RowCount * Constants.SizeOfInt); + if (NonZerosCount != 0) + { + Buffer.BlockCopy(_nonZeroValues, 0, sparseTarget._nonZeroValues, 0, NonZerosCount*Constants.SizeOfFloat); + Buffer.BlockCopy(_columnIndices, 0, sparseTarget._columnIndices, 0, NonZerosCount*Constants.SizeOfInt); + Buffer.BlockCopy(_rowIndex, 0, sparseTarget._rowIndex, 0, RowCount*Constants.SizeOfInt); } } diff --git a/src/Numerics/LinearAlgebra/Single/SparseVector.cs b/src/Numerics/LinearAlgebra/Single/SparseVector.cs index c962964b..ac5e8374 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseVector.cs @@ -326,8 +326,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single otherVector._nonZeroIndices = new int[NonZerosCount]; otherVector.NonZerosCount = NonZerosCount; - Buffer.BlockCopy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount * Constants.SizeOfFloat); - Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt); + if (NonZerosCount != 0) + { + Buffer.BlockCopy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount*Constants.SizeOfFloat); + Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount*Constants.SizeOfInt); + } } }