From 9f2d5e592329103bb5fabcb299303a6b2ed7d08a Mon Sep 17 00:00:00 2001 From: Marcus Cuda Date: Wed, 23 Mar 2011 20:55:20 +0800 Subject: [PATCH] dense matrix performance tweak. work item: 5680 --- .../LinearAlgebra/Complex/DenseMatrix.cs | 83 ++++++++++++++++-- .../LinearAlgebra/Complex32/DenseMatrix.cs | 83 ++++++++++++++++-- .../LinearAlgebra/Double/DenseMatrix.cs | 86 +++++++++++++++++-- .../LinearAlgebra/Single/DenseMatrix.cs | 83 ++++++++++++++++-- 4 files changed, 302 insertions(+), 33 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs index ebd77fe4..e93c55db 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs @@ -37,6 +37,20 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// public class DenseMatrix : Matrix { + /// + /// Number of rows. + /// + /// Using this instead of the RowCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _rowCount; + + /// + /// Number of columns. + /// + /// Using this instead of the ColumnCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _columnCount; + /// /// Initializes a new instance of the class. This matrix is square with a given size. /// @@ -47,6 +61,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public DenseMatrix(int order) : base(order) { + _rowCount = order; + _columnCount = order; Data = new Complex[order * order]; } @@ -62,6 +78,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public DenseMatrix(int rows, int columns) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new Complex[rows * columns]; } @@ -78,6 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public DenseMatrix(int rows, int columns, Complex value) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new Complex[rows * columns]; for (var i = 0; i < Data.Length; i++) { @@ -95,6 +115,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public DenseMatrix(int rows, int columns, Complex[] array) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = array; } @@ -106,14 +128,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public DenseMatrix(Complex[,] array) : base(array.GetLength(0), array.GetLength(1)) { - var rows = array.GetLength(0); - var columns = array.GetLength(1); - Data = new Complex[rows * columns]; - for (var i = 0; i < rows; i++) + _rowCount = array.GetLength(0); + _columnCount = array.GetLength(1); + Data = new Complex[_rowCount * _columnCount]; + for (var i = 0; i < _rowCount; i++) { - for (var j = 0; j < columns; j++) + for (var j = 0; j < _columnCount; j++) { - Data[(j * rows) + i] = array[i, j]; + Data[(j * _rowCount) + i] = array[i, j]; } } } @@ -157,6 +179,51 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new DenseVector(size); } + /// + /// Gets or sets the value at the given row and column. + /// + /// + /// The row of the element. + /// + /// + /// The column of the element. + /// + /// The value to get or set. + /// This method is ranged checked. and + /// to get and set values without range checking. + public override Complex this[int row, int column] + { + get + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + return Data[(column * _rowCount) + row]; + } + + set + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + Data[(column * _rowCount) + row] = value; + } + } + /// /// Retrieves the requested element without range checking. /// @@ -171,7 +238,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// public override Complex At(int row, int column) { - return Data[(column * RowCount) + row]; + return Data[(column * _rowCount) + row]; } /// @@ -188,7 +255,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// public override void At(int row, int column, Complex value) { - Data[(column * RowCount) + row] = value; + Data[(column * _rowCount) + row] = value; } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs index cc19f226..36367469 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs @@ -37,6 +37,20 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// public class DenseMatrix : Matrix { + /// + /// Number of rows. + /// + /// Using this instead of the RowCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _rowCount; + + /// + /// Number of columns. + /// + /// Using this instead of the ColumnCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _columnCount; + /// /// Initializes a new instance of the class. This matrix is square with a given size. /// @@ -47,6 +61,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public DenseMatrix(int order) : base(order) { + _rowCount = order; + _columnCount = order; Data = new Complex32[order * order]; } @@ -62,6 +78,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public DenseMatrix(int rows, int columns) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new Complex32[rows * columns]; } @@ -78,6 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public DenseMatrix(int rows, int columns, Complex32 value) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new Complex32[rows * columns]; for (var i = 0; i < Data.Length; i++) { @@ -95,6 +115,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public DenseMatrix(int rows, int columns, Complex32[] array) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = array; } @@ -106,14 +128,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public DenseMatrix(Complex32[,] array) : base(array.GetLength(0), array.GetLength(1)) { - var rows = array.GetLength(0); - var columns = array.GetLength(1); - Data = new Complex32[rows * columns]; - for (var i = 0; i < rows; i++) + _rowCount = array.GetLength(0); + _columnCount = array.GetLength(1); + Data = new Complex32[_rowCount * _columnCount]; + for (var i = 0; i < _rowCount; i++) { - for (var j = 0; j < columns; j++) + for (var j = 0; j < _columnCount; j++) { - Data[(j * rows) + i] = array[i, j]; + Data[(j * _rowCount) + i] = array[i, j]; } } } @@ -157,6 +179,51 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new DenseVector(size); } + /// + /// Gets or sets the value at the given row and column. + /// + /// + /// The row of the element. + /// + /// + /// The column of the element. + /// + /// The value to get or set. + /// This method is ranged checked. and + /// to get and set values without range checking. + public override Complex32 this[int row, int column] + { + get + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + return Data[(column * _rowCount) + row]; + } + + set + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + Data[(column * _rowCount) + row] = value; + } + } + /// /// Retrieves the requested element without range checking. /// @@ -171,7 +238,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// public override Complex32 At(int row, int column) { - return Data[(column * RowCount) + row]; + return Data[(column * _rowCount) + row]; } /// @@ -188,7 +255,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// public override void At(int row, int column, Complex32 value) { - Data[(column * RowCount) + row] = value; + Data[(column * _rowCount) + row] = value; } /// diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs index 43ea3959..fb9323bc 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs @@ -37,6 +37,20 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// public class DenseMatrix : Matrix { + /// + /// Number of rows. + /// + /// Using this instead of the RowCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _rowCount; + + /// + /// Number of columns. + /// + /// Using this instead of the ColumnCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _columnCount; + /// /// Initializes a new instance of the class. This matrix is square with a given size. /// @@ -47,6 +61,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double public DenseMatrix(int order) : base(order) { + _rowCount = order; + _columnCount = order; Data = new double[order * order]; } @@ -62,6 +78,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double public DenseMatrix(int rows, int columns) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new double[rows * columns]; } @@ -78,6 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double public DenseMatrix(int rows, int columns, double value) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new double[rows * columns]; for (var i = 0; i < Data.Length; i++) { @@ -95,6 +115,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double public DenseMatrix(int rows, int columns, double[] array) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = array; } @@ -106,14 +128,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double public DenseMatrix(double[,] array) : base(array.GetLength(0), array.GetLength(1)) { - var rows = array.GetLength(0); - var columns = array.GetLength(1); - Data = new double[rows * columns]; - for (var i = 0; i < rows; i++) + _rowCount = array.GetLength(0); + _columnCount = array.GetLength(1); + + Data = new double[_rowCount * _columnCount]; + for (var i = 0; i < _rowCount; i++) { - for (var j = 0; j < columns; j++) + for (var j = 0; j < _columnCount; j++) { - Data[(j * rows) + i] = array[i, j]; + Data[(j * _rowCount) + i] = array[i, j]; } } } @@ -157,6 +180,51 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new DenseVector(size); } + /// + /// Gets or sets the value at the given row and column. + /// + /// + /// The row of the element. + /// + /// + /// The column of the element. + /// + /// The value to get or set. + /// This method is ranged checked. and + /// to get and set values without range checking. + public override double this[int row, int column] + { + get + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + return Data[(column * _rowCount) + row]; + } + + set + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + Data[(column * _rowCount) + row] = value; + } + } + /// /// Retrieves the requested element without range checking. /// @@ -171,9 +239,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// public override double At(int row, int column) { - return Data[(column * RowCount) + row]; + return Data[(column * _rowCount) + row]; } - + /// /// Sets the value of the given element. /// @@ -188,7 +256,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// public override void At(int row, int column, double value) { - Data[(column * RowCount) + row] = value; + Data[(column * _rowCount) + row] = value; } /// diff --git a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs index ffc1c4b0..32f5038b 100644 --- a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs @@ -37,6 +37,20 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// public class DenseMatrix : Matrix { + /// + /// Number of rows. + /// + /// Using this instead of the RowCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _rowCount; + + /// + /// Number of columns. + /// + /// Using this instead of the ColumnCount property to speed up calculating + /// a matrix index in the data array. + private readonly int _columnCount; + /// /// Initializes a new instance of the class. This matrix is square with a given size. /// @@ -47,6 +61,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single public DenseMatrix(int order) : base(order) { + _rowCount = order; + _columnCount = order; Data = new float[order * order]; } @@ -62,6 +78,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single public DenseMatrix(int rows, int columns) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new float[rows * columns]; } @@ -78,6 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single public DenseMatrix(int rows, int columns, float value) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = new float[rows * columns]; for (var i = 0; i < Data.Length; i++) { @@ -95,6 +115,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single public DenseMatrix(int rows, int columns, float[] array) : base(rows, columns) { + _rowCount = rows; + _columnCount = columns; Data = array; } @@ -106,14 +128,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single public DenseMatrix(float[,] array) : base(array.GetLength(0), array.GetLength(1)) { - var rows = array.GetLength(0); - var columns = array.GetLength(1); - Data = new float[rows * columns]; - for (var i = 0; i < rows; i++) + _rowCount = array.GetLength(0); + _columnCount = array.GetLength(1); + Data = new float[_rowCount * _columnCount]; + for (var i = 0; i < _rowCount; i++) { - for (var j = 0; j < columns; j++) + for (var j = 0; j < _columnCount; j++) { - Data[(j * rows) + i] = array[i, j]; + Data[(j * _rowCount) + i] = array[i, j]; } } } @@ -157,6 +179,51 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new DenseVector(size); } + /// + /// Gets or sets the value at the given row and column. + /// + /// + /// The row of the element. + /// + /// + /// The column of the element. + /// + /// The value to get or set. + /// This method is ranged checked. and + /// to get and set values without range checking. + public override float this[int row, int column] + { + get + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + return Data[(column * _rowCount) + row]; + } + + set + { + if (row < 0 || row >= _rowCount) + { + throw new ArgumentOutOfRangeException("row"); + } + + if (column < 0 || column >= _columnCount) + { + throw new ArgumentOutOfRangeException("column"); + } + + Data[(column * _rowCount) + row] = value; + } + } + /// /// Retrieves the requested element without range checking. /// @@ -171,7 +238,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// public override float At(int row, int column) { - return Data[(column * RowCount) + row]; + return Data[(column * _rowCount) + row]; } /// @@ -188,7 +255,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// public override void At(int row, int column, float value) { - Data[(column * RowCount) + row] = value; + Data[(column * _rowCount) + row] = value; } ///