From 7a34beed26714c184c32f18e027600f43039408b Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Mon, 24 Oct 2011 23:15:43 +0200 Subject: [PATCH] Sparse Vectors: Equals now supports accidential zeros. Fixes gh-21. Equals previously returned always false in case of (asymmetric) accidential zeros. Instead, Equals now expects accidential zeros and treats them correctly (so we can allow arithmetic algorithms to generate accidential zeros, avoiding a lot of zero checks). --- .../LinearAlgebra/Complex/SparseVector.cs | 35 +++++++++++++------ .../LinearAlgebra/Complex32/SparseVector.cs | 35 +++++++++++++------ .../LinearAlgebra/Double/SparseVector.cs | 35 +++++++++++++------ .../LinearAlgebra/Single/SparseVector.cs | 35 +++++++++++++------ 4 files changed, 100 insertions(+), 40 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs index ef67a10e..7d9b5492 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs @@ -1446,25 +1446,40 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return true; } - var sparseVector = other as SparseVector; - - if (sparseVector == null) + var otherSparse = other as SparseVector; + if (otherSparse == null) { return base.Equals(other); } - if (NonZerosCount != sparseVector.NonZerosCount) + int i = 0, j = 0; + while (i < NonZerosCount || j < otherSparse.NonZerosCount) { - return false; - } + if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j]) + { + if (_nonZeroValues[i++] != Complex.Zero) + { + return false; + } + continue; + } - // If all else fails, perform element wise comparison. - for (var index = 0; index < NonZerosCount; index++) - { - if (!_nonZeroValues[index].AlmostEqual(sparseVector._nonZeroValues[index]) || (_nonZeroIndices[index] != sparseVector._nonZeroIndices[index])) + if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i]) + { + if (otherSparse._nonZeroValues[j++] != Complex.Zero) + { + return false; + } + continue; + } + + if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j])) { return false; } + + i++; + j++; } return true; diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs index 0b6858aa..753ffedf 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs @@ -1476,25 +1476,40 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return true; } - var sparseVector = other as SparseVector; - - if (sparseVector == null) + var otherSparse = other as SparseVector; + if (otherSparse == null) { return base.Equals(other); } - if (NonZerosCount != sparseVector.NonZerosCount) + int i = 0, j = 0; + while (i < NonZerosCount || j < otherSparse.NonZerosCount) { - return false; - } + if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j]) + { + if (_nonZeroValues[i++] != Complex32.Zero) + { + return false; + } + continue; + } - // If all else fails, perform element wise comparison. - for (var index = 0; index < NonZerosCount; index++) - { - if (!_nonZeroValues[index].AlmostEqual(sparseVector._nonZeroValues[index]) || (_nonZeroIndices[index] != sparseVector._nonZeroIndices[index])) + if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i]) + { + if (otherSparse._nonZeroValues[j++] != Complex32.Zero) + { + return false; + } + continue; + } + + if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j])) { return false; } + + i++; + j++; } return true; diff --git a/src/Numerics/LinearAlgebra/Double/SparseVector.cs b/src/Numerics/LinearAlgebra/Double/SparseVector.cs index 85836244..fb2c9d5f 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseVector.cs @@ -1506,25 +1506,40 @@ namespace MathNet.Numerics.LinearAlgebra.Double return true; } - var sparseVector = other as SparseVector; - - if (sparseVector == null) + var otherSparse = other as SparseVector; + if (otherSparse == null) { return base.Equals(other); } - if (NonZerosCount != sparseVector.NonZerosCount) + int i = 0, j = 0; + while (i < NonZerosCount || j < otherSparse.NonZerosCount) { - return false; - } + if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j]) + { + if (_nonZeroValues[i++] != 0d) + { + return false; + } + continue; + } - // If all else fails, perform element wise comparison. - for (var index = 0; index < NonZerosCount; index++) - { - if (!_nonZeroValues[index].AlmostEqual(sparseVector._nonZeroValues[index]) || (_nonZeroIndices[index] != sparseVector._nonZeroIndices[index])) + if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i]) + { + if (otherSparse._nonZeroValues[j++] != 0d) + { + return false; + } + continue; + } + + if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j])) { return false; } + + i++; + j++; } return true; diff --git a/src/Numerics/LinearAlgebra/Single/SparseVector.cs b/src/Numerics/LinearAlgebra/Single/SparseVector.cs index a77a7599..5d036854 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseVector.cs @@ -1516,25 +1516,40 @@ namespace MathNet.Numerics.LinearAlgebra.Single return true; } - var sparseVector = other as SparseVector; - - if (sparseVector == null) + var otherSparse = other as SparseVector; + if (otherSparse == null) { return base.Equals(other); } - if (NonZerosCount != sparseVector.NonZerosCount) + int i = 0, j = 0; + while (i < NonZerosCount || j < otherSparse.NonZerosCount) { - return false; - } + if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j]) + { + if (_nonZeroValues[i++] != 0f) + { + return false; + } + continue; + } - // If all else fails, perform element wise comparison. - for (var index = 0; index < NonZerosCount; index++) - { - if (!_nonZeroValues[index].AlmostEqual(sparseVector._nonZeroValues[index]) || (_nonZeroIndices[index] != sparseVector._nonZeroIndices[index])) + if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i]) + { + if (otherSparse._nonZeroValues[j++] != 0f) + { + return false; + } + continue; + } + + if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j])) { return false; } + + i++; + j++; } return true;