Browse Source

LA: transpose inplace

v3
Christoph Ruegg 10 years ago
parent
commit
bcab9f1a96
  1. 14
      src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs
  2. 5
      src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs
  3. 24
      src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
  4. 40
      src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
  5. 49
      src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs

14
src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs

@ -595,6 +595,20 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
target.Values = values.ToArray();
}
internal override void TransposeSquareInplaceUnchecked()
{
for (var j = 0; j < ColumnCount; j++)
{
var index = j * RowCount;
for (var i = 0; i < j; i++)
{
T swap = Data[index + i];
Data[index + i] = Data[i*ColumnCount + j];
Data[i*ColumnCount + j] = swap;
}
}
}
// EXTRACT
public override T[] ToRowMajorArray()

5
src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs

@ -491,6 +491,11 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
CopyToUnchecked(target, existingData);
}
internal override void TransposeSquareInplaceUnchecked()
{
// nothing to do
}
// EXTRACT
public override T[] ToRowMajorArray()

24
src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs

@ -467,17 +467,18 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
throw new ArgumentNullException("target");
}
if (ReferenceEquals(this, target))
{
throw new NotSupportedException("In-place transpose is not supported.");
}
if (RowCount != target.ColumnCount || ColumnCount != target.RowCount)
{
var message = string.Format(Resources.ArgumentMatrixDimensions2, RowCount + "x" + ColumnCount, target.RowCount + "x" + target.ColumnCount);
throw new ArgumentException(message, "target");
}
if (ReferenceEquals(this, target))
{
TransposeSquareInplaceUnchecked();
return;
}
TransposeToUnchecked(target, existingData);
}
@ -492,6 +493,19 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
internal virtual void TransposeSquareInplaceUnchecked()
{
for (int j = 0; j < ColumnCount; j++)
{
for (int i = 0; i < j; i++)
{
T swap = At(i, j);
At(i, j, At(j, i));
At(j, i, swap);
}
}
}
// EXTRACT
public virtual T[] ToRowMajorArray()

40
src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs

@ -1154,6 +1154,46 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
internal override void TransposeSquareInplaceUnchecked()
{
var cx = new T[ValueCount]; //target.Values;
var cp = new int[RowCount + 1];
var ci = new int[ValueCount]; //target.ColumnIndices;
// Column counts
int[] w = new int[ColumnCount];
for (int p = 0; p < RowPointers[RowCount]; p++)
{
w[ColumnIndices[p]]++;
}
// Column pointers
int nz = 0;
for (int i = 0; i < ColumnCount; i++)
{
cp[i] = nz;
nz += w[i];
w[i] = cp[i];
}
cp[ColumnCount] = nz;
for (int i = 0; i < RowCount; i++)
{
for (int p = RowPointers[i]; p < RowPointers[i + 1]; p++)
{
int j = w[ColumnIndices[p]]++;
// Place A(i,j) as entry C(j,i)
ci[j] = i;
cx[j] = Values[p];
}
}
Array.Copy(cx, 0, Values, 0, ValueCount);
Buffer.BlockCopy(ci, 0, ColumnIndices, 0, ValueCount * Constants.SizeOfInt);
Buffer.BlockCopy(cp, 0, RowPointers, 0, (RowCount + 1) * Constants.SizeOfInt);
}
// EXTRACT
public override T[] ToRowMajorArray()

49
src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs

@ -27,6 +27,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.LinearAlgebra;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
@ -62,6 +63,54 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
}
}
/// <summary>
/// Can transpose a matrix into a result.
/// </summary>
/// <param name="name">Matrix name.</param>
[TestCase("Singular3x3")]
[TestCase("Square3x3")]
[TestCase("Square4x4")]
[TestCase("Tall3x2")]
[TestCase("Wide2x3")]
public void CanTransposeMatrixResult(string name)
{
var matrix = TestMatrices[name];
var transpose = Matrix<double>.Build.SameAs(matrix, matrix.ColumnCount, matrix.RowCount);
matrix.Transpose(transpose);
Assert.AreNotSame(matrix, transpose);
Assert.AreEqual(matrix.RowCount, transpose.ColumnCount);
Assert.AreEqual(matrix.ColumnCount, transpose.RowCount);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
Assert.AreEqual(matrix[i, j], transpose[j, i]);
}
}
}
/// <summary>
/// Can transpose a square matrix inplace.
/// </summary>
/// <param name="name">Matrix name.</param>
[TestCase("Square4x4")]
public void CanTransposeSquareMatrixInplace(string name)
{
var matrix = TestMatrices[name];
var transpose = matrix.Clone();
transpose.Transpose(transpose);
Assert.AreNotSame(matrix, transpose);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
Assert.AreEqual(matrix[i, j], transpose[j, i]);
}
}
}
/// <summary>
/// Can compute Frobenius norm.
/// </summary>

Loading…
Cancel
Save