diff --git a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs
index 90c6bafa..0312a85a 100644
--- a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs
+++ b/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()
diff --git a/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs
index 05ae5191..58a315bd 100644
--- a/src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs
+++ b/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()
diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
index 3f3f14e7..b8c65143 100644
--- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
+++ b/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()
diff --git a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
index 840269e3..c5e29c31 100644
--- a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
+++ b/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()
diff --git a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs
index 9bc51296..94b60341 100644
--- a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs
+++ b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs
@@ -27,6 +27,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+using MathNet.Numerics.LinearAlgebra;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
@@ -62,6 +63,54 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
}
}
+ ///
+ /// Can transpose a matrix into a result.
+ ///
+ /// Matrix name.
+ [TestCase("Singular3x3")]
+ [TestCase("Square3x3")]
+ [TestCase("Square4x4")]
+ [TestCase("Tall3x2")]
+ [TestCase("Wide2x3")]
+ public void CanTransposeMatrixResult(string name)
+ {
+ var matrix = TestMatrices[name];
+ var transpose = Matrix.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]);
+ }
+ }
+ }
+
+ ///
+ /// Can transpose a square matrix inplace.
+ ///
+ /// Matrix name.
+ [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]);
+ }
+ }
+ }
+
///
/// Can compute Frobenius norm.
///