Skip to content

Commit 5ff5a75

Browse files
committed
LA: fix a critical bug in SparseMatrix.Add when adding a matrix to itself #341
1 parent b5a4175 commit 5ff5a75

File tree

8 files changed

+166
-7
lines changed

8 files changed

+166
-7
lines changed

src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ protected override void DoAdd(Matrix<Complex> other, Matrix<Complex> result)
726726
CopyTo(result);
727727
}
728728

729-
Control.LinearAlgebraProvider.ScaleArray(2.0, _storage.Values, _storage.Values);
729+
Control.LinearAlgebraProvider.ScaleArray(2.0, sparseResult._storage.Values, sparseResult._storage.Values);
730730
return;
731731
}
732732

src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ protected override void DoAdd(Matrix<Complex32> other, Matrix<Complex32> result)
721721
CopyTo(result);
722722
}
723723

724-
Control.LinearAlgebraProvider.ScaleArray(2.0f, _storage.Values, _storage.Values);
724+
Control.LinearAlgebraProvider.ScaleArray(2.0f, sparseResult._storage.Values, sparseResult._storage.Values);
725725
return;
726726
}
727727

src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ protected override void DoAdd(Matrix<double> other, Matrix<double> result)
721721
CopyTo(result);
722722
}
723723

724-
Control.LinearAlgebraProvider.ScaleArray(2.0, _storage.Values, _storage.Values);
724+
Control.LinearAlgebraProvider.ScaleArray(2.0, sparseResult._storage.Values, sparseResult._storage.Values);
725725
return;
726726
}
727727

src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public static SparseMatrix OfColumns(IEnumerable<IEnumerable<float>> data)
155155
{
156156
return OfColumnArrays(data.Select(v => v.ToArray()).ToArray());
157157
}
158-
158+
159159
/// <summary>
160160
/// Create a new sparse matrix as a copy of the given enumerable of enumerable columns.
161161
/// Each enumerable in the master enumerable specifies a column.
@@ -725,7 +725,7 @@ protected override void DoAdd(Matrix<float> other, Matrix<float> result)
725725
CopyTo(result);
726726
}
727727

728-
Control.LinearAlgebraProvider.ScaleArray(2.0f, _storage.Values, _storage.Values);
728+
Control.LinearAlgebraProvider.ScaleArray(2.0f, sparseResult._storage.Values, sparseResult._storage.Values);
729729
return;
730730
}
731731

@@ -1095,7 +1095,7 @@ protected override void DoTransposeAndMultiply(Matrix<float> other, Matrix<float
10951095
for (var i = 0; i < RowCount; i++)
10961096
{
10971097
// Multiply row of matrix A on row of matrix B
1098-
1098+
10991099
var startIndexThis = rowPointers[i];
11001100
var endIndexThis = rowPointers[i + 1];
11011101

src/UnitTests/LinearAlgebraTests/Complex/MatrixTests.Arithmetic.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,46 @@ public void CanAddMatrix(string mtxA, string mtxB)
251251
}
252252
}
253253

254+
/// <summary>
255+
/// Can add a matrix.
256+
/// </summary>
257+
/// <param name="mtx">Matrix name.</param>
258+
[TestCase("Square3x3")]
259+
[TestCase("Tall3x2")]
260+
public void CanAddMatrixToSelf(string mtx)
261+
{
262+
var matrix = TestMatrices[mtx].Clone();
263+
264+
var result = matrix.Add(matrix);
265+
for (var i = 0; i < matrix.RowCount; i++)
266+
{
267+
for (var j = 0; j < matrix.ColumnCount; j++)
268+
{
269+
Assert.AreEqual(result[i, j], 2*matrix[i, j]);
270+
}
271+
}
272+
}
273+
274+
/// <summary>
275+
/// Can subtract a matrix.
276+
/// </summary>
277+
/// <param name="mtx">Matrix name.</param>
278+
[TestCase("Square3x3")]
279+
[TestCase("Tall3x2")]
280+
public void CanSubtractMatrixFromSelf(string mtx)
281+
{
282+
var matrix = TestMatrices[mtx].Clone();
283+
284+
var result = matrix.Subtract(matrix);
285+
for (var i = 0; i < matrix.RowCount; i++)
286+
{
287+
for (var j = 0; j < matrix.ColumnCount; j++)
288+
{
289+
Assert.AreEqual(result[i, j], Complex.Zero);
290+
}
291+
}
292+
}
293+
254294
/// <summary>
255295
/// Adding a matrix with fewer columns throws <c>ArgumentOutOfRangeException</c>.
256296
/// </summary>

src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.Arithmetic.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,46 @@ public void CanAddMatrix(string mtxA, string mtxB)
247247
}
248248
}
249249

250+
/// <summary>
251+
/// Can add a matrix.
252+
/// </summary>
253+
/// <param name="mtx">Matrix name.</param>
254+
[TestCase("Square3x3")]
255+
[TestCase("Tall3x2")]
256+
public void CanAddMatrixToSelf(string mtx)
257+
{
258+
var matrix = TestMatrices[mtx].Clone();
259+
260+
var result = matrix.Add(matrix);
261+
for (var i = 0; i < matrix.RowCount; i++)
262+
{
263+
for (var j = 0; j < matrix.ColumnCount; j++)
264+
{
265+
Assert.AreEqual(result[i, j], 2*matrix[i, j]);
266+
}
267+
}
268+
}
269+
270+
/// <summary>
271+
/// Can subtract a matrix.
272+
/// </summary>
273+
/// <param name="mtx">Matrix name.</param>
274+
[TestCase("Square3x3")]
275+
[TestCase("Tall3x2")]
276+
public void CanSubtractMatrixFromSelf(string mtx)
277+
{
278+
var matrix = TestMatrices[mtx].Clone();
279+
280+
var result = matrix.Subtract(matrix);
281+
for (var i = 0; i < matrix.RowCount; i++)
282+
{
283+
for (var j = 0; j < matrix.ColumnCount; j++)
284+
{
285+
Assert.AreEqual(result[i, j], Complex32.Zero);
286+
}
287+
}
288+
}
289+
250290
/// <summary>
251291
/// Adding a matrix with fewer columns throws <c>ArgumentOutOfRangeException</c>.
252292
/// </summary>

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
using System;
2828
using MathNet.Numerics.Distributions;
2929
using MathNet.Numerics.LinearAlgebra;
30-
using MathNet.Numerics.LinearAlgebra.Double;
3130
using NUnit.Framework;
3231

3332
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
@@ -241,6 +240,46 @@ public void CanAddMatrix(string mtxA, string mtxB)
241240
}
242241
}
243242

243+
/// <summary>
244+
/// Can add a matrix.
245+
/// </summary>
246+
/// <param name="mtx">Matrix name.</param>
247+
[TestCase("Square3x3")]
248+
[TestCase("Tall3x2")]
249+
public void CanAddMatrixToSelf(string mtx)
250+
{
251+
var matrix = TestMatrices[mtx].Clone();
252+
253+
var result = matrix.Add(matrix);
254+
for (var i = 0; i < matrix.RowCount; i++)
255+
{
256+
for (var j = 0; j < matrix.ColumnCount; j++)
257+
{
258+
Assert.AreEqual(result[i, j], 2*matrix[i, j]);
259+
}
260+
}
261+
}
262+
263+
/// <summary>
264+
/// Can subtract a matrix.
265+
/// </summary>
266+
/// <param name="mtx">Matrix name.</param>
267+
[TestCase("Square3x3")]
268+
[TestCase("Tall3x2")]
269+
public void CanSubtractMatrixFromSelf(string mtx)
270+
{
271+
var matrix = TestMatrices[mtx].Clone();
272+
273+
var result = matrix.Subtract(matrix);
274+
for (var i = 0; i < matrix.RowCount; i++)
275+
{
276+
for (var j = 0; j < matrix.ColumnCount; j++)
277+
{
278+
Assert.AreEqual(result[i, j], 0d);
279+
}
280+
}
281+
}
282+
244283
/// <summary>
245284
/// Adding a matrix with fewer columns throws <c>ArgumentOutOfRangeException</c>.
246285
/// </summary>

src/UnitTests/LinearAlgebraTests/Single/MatrixTests.Arithmetic.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,46 @@ public void CanAddMatrix(string mtxA, string mtxB)
241241
}
242242
}
243243

244+
/// <summary>
245+
/// Can add a matrix.
246+
/// </summary>
247+
/// <param name="mtx">Matrix name.</param>
248+
[TestCase("Square3x3")]
249+
[TestCase("Tall3x2")]
250+
public void CanAddMatrixToSelf(string mtx)
251+
{
252+
var matrix = TestMatrices[mtx].Clone();
253+
254+
var result = matrix.Add(matrix);
255+
for (var i = 0; i < matrix.RowCount; i++)
256+
{
257+
for (var j = 0; j < matrix.ColumnCount; j++)
258+
{
259+
Assert.AreEqual(result[i, j], 2*matrix[i, j]);
260+
}
261+
}
262+
}
263+
264+
/// <summary>
265+
/// Can subtract a matrix.
266+
/// </summary>
267+
/// <param name="mtx">Matrix name.</param>
268+
[TestCase("Square3x3")]
269+
[TestCase("Tall3x2")]
270+
public void CanSubtractMatrixFromSelf(string mtx)
271+
{
272+
var matrix = TestMatrices[mtx].Clone();
273+
274+
var result = matrix.Subtract(matrix);
275+
for (var i = 0; i < matrix.RowCount; i++)
276+
{
277+
for (var j = 0; j < matrix.ColumnCount; j++)
278+
{
279+
Assert.AreEqual(result[i, j], 0f);
280+
}
281+
}
282+
}
283+
244284
/// <summary>
245285
/// Adding a matrix with fewer columns throws <c>ArgumentOutOfRangeException</c>.
246286
/// </summary>

0 commit comments

Comments
 (0)