Browse Source

Linear Algebra: fix bug in sparse vector pointwise multiply/divide to itself #390

pull/399/head
Christoph Ruegg 10 years ago
parent
commit
b3bb2d1e73
  1. 32
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  2. 32
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  3. 32
      src/Numerics/LinearAlgebra/Double/SparseVector.cs
  4. 32
      src/Numerics/LinearAlgebra/Single/SparseVector.cs
  5. 2
      src/UnitTests/LinearAlgebraTests/Complex/SparseVectorTest.cs
  6. 64
      src/UnitTests/LinearAlgebraTests/Double/SparseVectorTest.cs

32
src/Numerics/LinearAlgebra/Complex/SparseVector.cs

@ -778,7 +778,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<Complex> other, Vector<Complex> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, other) && ReferenceEquals(this, result))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -787,35 +787,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<Complex> divisor, Vector<Complex> result)
{
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / divisor.At(index));
}
base.DoPointwiseMultiply(other, result);
}
}

32
src/Numerics/LinearAlgebra/Complex32/SparseVector.cs

@ -773,7 +773,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<Complex32> other, Vector<Complex32> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, other) && ReferenceEquals(this, result))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -782,35 +782,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<Complex32> divisor, Vector<Complex32> result)
{
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / divisor.At(index));
}
base.DoPointwiseMultiply(other, result);
}
}

32
src/Numerics/LinearAlgebra/Double/SparseVector.cs

@ -820,7 +820,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<double> other, Vector<double> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, other) && ReferenceEquals(this, result))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -829,35 +829,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<double> divisor, Vector<double> result)
{
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / divisor.At(index));
}
base.DoPointwiseMultiply(other, result);
}
}

32
src/Numerics/LinearAlgebra/Single/SparseVector.cs

@ -821,7 +821,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<float> other, Vector<float> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, other) && ReferenceEquals(this, result))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -830,35 +830,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<float> divisor, Vector<float> result)
{
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / divisor.At(index));
}
base.DoPointwiseMultiply(other, result);
}
}

2
src/UnitTests/LinearAlgebraTests/Complex/SparseVectorTest.cs

@ -362,7 +362,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
}
/// <summary>
/// Test for issues #52. When setting previous non-zero values to zero,
/// Test for issue #52. When setting previous non-zero values to zero,
/// DoMultiply would copy non-zero values to the result, but use the
/// length of nonzerovalues instead of NonZerosCount.
/// </summary>

64
src/UnitTests/LinearAlgebraTests/Double/SparseVectorTest.cs

@ -355,6 +355,70 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>
/// Can pointwise divide a sparse vector.
/// </summary>
[Test]
public void CanPointwiseDivideSparseVector()
{
var zeroArray = new[] { 0.0, 1.0, 0.0, 1.0, 0.0 };
var vector1 = Vector<double>.Build.SparseOfEnumerable(zeroArray);
var vector2 = Vector<double>.Build.SparseOfEnumerable(Data);
var result = Vector<double>.Build.Sparse(vector1.Count);
vector1.PointwiseDivide(vector2, result);
for (var i = 0; i < vector1.Count; i++)
{
Assert.AreEqual(zeroArray[i] / Data[i], result[i]);
}
var resultStorage = (SparseVectorStorage<double>)result.Storage;
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>
/// Can pointwise multiple a sparse vector to itself.
/// </summary>
[Test]
public void CanPointwiseMultiplyToSelfSparseVector()
{
var zeroArray = new[] { 0.0, 2.0, 0.0, 2.0, 0.0 };
var vector = Vector<double>.Build.SparseOfEnumerable(zeroArray);
var result = Vector<double>.Build.Sparse(vector.Count);
vector.PointwiseMultiply(vector, result);
for (var i = 0; i < vector.Count; i++)
{
Assert.AreEqual(zeroArray[i] * zeroArray[i], result[i]);
}
var resultStorage = (SparseVectorStorage<double>)result.Storage;
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>
/// Can pointwise divide a sparse vector to itself.
/// </summary>
[Test]
public void CanPointwiseDivideToSelfSparseVector()
{
var zeroArray = new[] { 0.0, 2.0, 0.0, 2.0, 0.0 };
var vector = Vector<double>.Build.SparseOfEnumerable(zeroArray);
var result = Vector<double>.Build.Sparse(vector.Count);
vector.PointwiseDivide(vector, result);
for (var i = 0; i < vector.Count; i++)
{
Assert.AreEqual(zeroArray[i] / zeroArray[i], result[i]);
}
var resultStorage = (SparseVectorStorage<double>)result.Storage;
Assert.AreEqual(5, resultStorage.ValueCount);
}
/// <summary>
/// Can outer multiple two sparse vectors. Checking fix for workitem 5696.
/// </summary>

Loading…
Cancel
Save