diff --git a/src/Numerics/LinearAlgebra/Matrix.cs b/src/Numerics/LinearAlgebra/Matrix.cs
index 223bcf96..4c67a260 100644
--- a/src/Numerics/LinearAlgebra/Matrix.cs
+++ b/src/Numerics/LinearAlgebra/Matrix.cs
@@ -1745,33 +1745,57 @@ namespace MathNet.Numerics.LinearAlgebra
return Storage.Fold2(other.Storage, f, state, zeros);
}
+ ///
+ /// Returns a tuple with the index and value of the first element satisfying a predicate, or null if none is found.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
public Tuple Find(Func predicate, Zeros zeros = Zeros.AllowSkip)
{
return Storage.Find(predicate, zeros);
}
+ ///
+ /// Returns a tuple with the index and values of the first element pair of two matrices of the same size satisfying a predicate, or null if none is found.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
public Tuple Find2(Func predicate, Matrix other, Zeros zeros = Zeros.AllowSkip)
where TOther : struct, IEquatable, IFormattable
{
return Storage.Find2(other.Storage, predicate, zeros);
}
+ ///
+ /// Returns true if at least one element satisfies a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
public bool Exists(Func predicate, Zeros zeros = Zeros.AllowSkip)
{
return Storage.Find(predicate, zeros) != null;
}
+ ///
+ /// Returns true if at least one element pairs of two matrices of the same size satisfies a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
public bool Exists2(Func predicate, Matrix other, Zeros zeros = Zeros.AllowSkip)
where TOther : struct, IEquatable, IFormattable
{
return Storage.Find2(other.Storage, predicate, zeros) != null;
}
+ ///
+ /// Returns true if all elements satisfy a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
public bool ForAll(Func predicate, Zeros zeros = Zeros.AllowSkip)
{
return Storage.Find(x => !predicate(x), zeros) == null;
}
+ ///
+ /// Returns true if all element pairs of two matrices of the same size satisfy a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
public bool ForAll2(Func predicate, Matrix other, Zeros zeros = Zeros.AllowSkip)
where TOther : struct, IEquatable, IFormattable
{
diff --git a/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs
index 2cbaaee1..c52b0f82 100644
--- a/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs
+++ b/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs
@@ -90,6 +90,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
Data[index] = value;
}
+ // CLEARING
+
public override void Clear()
{
Array.Clear(Data, 0, Data.Length);
@@ -353,6 +355,71 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
+ // FIND
+
+ public override Tuple Find(Func predicate, Zeros zeros)
+ {
+ for (int i = 0; i < Data.Length; i++)
+ {
+ if (predicate(Data[i]))
+ {
+ return new Tuple(i, Data[i]);
+ }
+ }
+ return null;
+ }
+
+ internal override Tuple Find2Unchecked(VectorStorage other, Func predicate, Zeros zeros)
+ {
+ var denseOther = other as DenseVectorStorage;
+ if (denseOther != null)
+ {
+ TOther[] otherData = denseOther.Data;
+ for (int i = 0; i < Data.Length; i++)
+ {
+ if (predicate(Data[i], otherData[i]))
+ {
+ return new Tuple(i, Data[i], otherData[i]);
+
+ }
+ }
+ return null;
+ }
+
+ var sparseOther = other as SparseVectorStorage;
+ if (sparseOther != null)
+ {
+ int[] otherIndices = sparseOther.Indices;
+ TOther[] otherValues = sparseOther.Values;
+ int otherValueCount = sparseOther.ValueCount;
+ TOther otherZero = BuilderInstance.Matrix.Zero;
+ int k = 0;
+ for (int i = 0; i < Data.Length; i++)
+ {
+ if (k < otherValueCount && otherIndices[k] == i)
+ {
+ if (predicate(Data[i], otherValues[k]))
+ {
+ return new Tuple(i, Data[i], otherValues[k]);
+ }
+ k++;
+ }
+ else
+ {
+ if (predicate(Data[i], otherZero))
+ {
+ return new Tuple(i, Data[i], otherZero);
+ }
+ }
+ }
+ return null;
+ }
+
+ // FALLBACK
+
+ return base.Find2Unchecked(other, predicate, zeros);
+ }
+
// FUNCTIONAL COMBINATORS
internal override void MapToUnchecked(VectorStorage target, Func f, Zeros zeros, ExistingData existingData)
diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
index 778aca5e..3fcdbb45 100644
--- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
+++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
@@ -794,6 +794,44 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
+ public void Map2To(MatrixStorage target, MatrixStorage other, Func f, Zeros zeros, ExistingData existingData)
+ {
+ if (target == null)
+ {
+ throw new ArgumentNullException("target");
+ }
+
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (RowCount != target.RowCount || ColumnCount != target.ColumnCount)
+ {
+ var message = string.Format(Resources.ArgumentMatrixDimensions2, RowCount + "x" + ColumnCount, target.RowCount + "x" + target.ColumnCount);
+ throw new ArgumentException(message, "target");
+ }
+
+ if (RowCount != other.RowCount || ColumnCount != other.ColumnCount)
+ {
+ var message = string.Format(Resources.ArgumentMatrixDimensions2, RowCount + "x" + ColumnCount, other.RowCount + "x" + other.ColumnCount);
+ throw new ArgumentException(message, "other");
+ }
+
+ Map2ToUnchecked(target, other, f, zeros, existingData);
+ }
+
+ internal virtual void Map2ToUnchecked(MatrixStorage target, MatrixStorage other, Func f, Zeros zeros, ExistingData existingData)
+ {
+ for (int i = 0; i < RowCount; i++)
+ {
+ for (int j = 0; j < ColumnCount; j++)
+ {
+ target.At(i, j, f(At(i, j), other.At(i, j)));
+ }
+ }
+ }
+
// FUNCTIONAL COMBINATORS: FOLD
/// The state array will not be modified, unless it is the same instance as the target array (which is allowed).
diff --git a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
index d839ebb7..5c42e85d 100644
--- a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
+++ b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
@@ -1367,7 +1367,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
TOther[] otherData = diagonalOther.Data;
TOther otherZero = BuilderInstance.Matrix.Zero;
- if (zeros == Zeros.Include)
+ // Full Scan
+ if (zeros == Zeros.Include && predicate(Zero, otherZero))
{
int k = 0;
for (int row = 0; row < RowCount; row++)
@@ -1384,6 +1385,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return null;
}
+ // Sparse Scan
for (int row = 0; row < RowCount; row++)
{
bool diagonal = false;
@@ -1446,35 +1448,31 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
for (int row = 0; row < RowCount; row++)
{
- var startIndex = RowPointers[row];
var endIndex = RowPointers[row + 1];
- var otherStartIndex = otherRowPointers[row];
var otherEndIndex = otherRowPointers[row + 1];
-
- var j1 = startIndex;
- var j2 = otherStartIndex;
-
- while (j1 < endIndex || j2 < otherEndIndex)
+ var k = RowPointers[row];
+ var otherk = otherRowPointers[row];
+ while (k < endIndex || otherk < otherEndIndex)
{
- if (j1 == endIndex || j2 < otherEndIndex && ColumnIndices[j1] > otherColumnIndices[j2])
+ if (k == endIndex || otherk < otherEndIndex && ColumnIndices[k] > otherColumnIndices[otherk])
{
- if (predicate(Zero, otherValues[j2++]))
+ if (predicate(Zero, otherValues[otherk++]))
{
- return new Tuple(row, otherColumnIndices[j2 - 1], Zero, otherValues[j2 - 1]);
+ return new Tuple(row, otherColumnIndices[otherk - 1], Zero, otherValues[otherk - 1]);
}
}
- else if (j2 == otherEndIndex || ColumnIndices[j1] < otherColumnIndices[j2])
+ else if (otherk == otherEndIndex || ColumnIndices[k] < otherColumnIndices[otherk])
{
- if (predicate(Values[j1++], otherZero))
+ if (predicate(Values[k++], otherZero))
{
- return new Tuple(row, ColumnIndices[j1 - 1], Values[j1 - 1], otherZero);
+ return new Tuple(row, ColumnIndices[k - 1], Values[k - 1], otherZero);
}
}
else
{
- if (predicate(Values[j1++], otherValues[j2++]))
+ if (predicate(Values[k++], otherValues[otherk++]))
{
- return new Tuple(row, ColumnIndices[j1 - 1], Values[j1 - 1], otherValues[j2 - 1]);
+ return new Tuple(row, ColumnIndices[k - 1], Values[k - 1], otherValues[otherk - 1]);
}
}
}
diff --git a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs
index 0f383cb3..8e78c3cd 100644
--- a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs
+++ b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs
@@ -183,42 +183,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return delta;
}
- public override void Clear()
- {
- ValueCount = 0;
- }
-
- public override void Clear(int index, int count)
- {
- if (index == 0 && count == Length)
- {
- Clear();
- return;
- }
-
- var first = Array.BinarySearch(Indices, 0, ValueCount, index);
- var last = Array.BinarySearch(Indices, 0, ValueCount, index + count - 1);
- if (first < 0) first = ~first;
- if (last < 0) last = ~last - 1;
- int itemCount = last - first + 1;
-
- if (itemCount > 0)
- {
- Array.Copy(Values, first + count, Values, first, ValueCount - first - count);
- Array.Copy(Indices, first + count, Indices, first, ValueCount - first - count);
-
- ValueCount -= count;
- }
-
- // Check whether we need to shrink the arrays. This is reasonable to do if
- // there are a lot of non-zero elements and storage is two times bigger
- if ((ValueCount > 1024) && (ValueCount < Indices.Length / 2))
- {
- Array.Resize(ref Values, ValueCount);
- Array.Resize(ref Indices, ValueCount);
- }
- }
-
public override bool Equals(VectorStorage other)
{
// Reject equality when the argument is null or has a different shape.
@@ -293,6 +257,44 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return hash;
}
+ // CLEARING
+
+ public override void Clear()
+ {
+ ValueCount = 0;
+ }
+
+ public override void Clear(int index, int count)
+ {
+ if (index == 0 && count == Length)
+ {
+ Clear();
+ return;
+ }
+
+ var first = Array.BinarySearch(Indices, 0, ValueCount, index);
+ var last = Array.BinarySearch(Indices, 0, ValueCount, index + count - 1);
+ if (first < 0) first = ~first;
+ if (last < 0) last = ~last - 1;
+ int itemCount = last - first + 1;
+
+ if (itemCount > 0)
+ {
+ Array.Copy(Values, first + count, Values, first, ValueCount - first - count);
+ Array.Copy(Indices, first + count, Indices, first, ValueCount - first - count);
+
+ ValueCount -= count;
+ }
+
+ // Check whether we need to shrink the arrays. This is reasonable to do if
+ // there are a lot of non-zero elements and storage is two times bigger
+ if ((ValueCount > 1024) && (ValueCount < Indices.Length / 2))
+ {
+ Array.Resize(ref Values, ValueCount);
+ Array.Resize(ref Indices, ValueCount);
+ }
+ }
+
// INITIALIZATION
public static SparseVectorStorage OfVector(VectorStorage vector)
@@ -645,6 +647,117 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
+ // FIND
+
+ public override Tuple Find(Func predicate, Zeros zeros)
+ {
+ for (int i = 0; i < ValueCount; i++)
+ {
+ if (predicate(Values[i]))
+ {
+ return new Tuple(Indices[i], Values[i]);
+ }
+ }
+ if (zeros == Zeros.Include && ValueCount < Length && predicate(Zero))
+ {
+ for (int i = 0; i < Length; i++)
+ {
+ if (i >= ValueCount || Indices[i] != i)
+ {
+ return new Tuple(i, Zero);
+ }
+ }
+ }
+ return null;
+ }
+
+ internal override Tuple Find2Unchecked(VectorStorage other, Func predicate, Zeros zeros)
+ {
+ var denseOther = other as DenseVectorStorage;
+ if (denseOther != null)
+ {
+ TOther[] otherData = denseOther.Data;
+ int k = 0;
+ for (int i = 0; i < otherData.Length; i++)
+ {
+ if (k < ValueCount && Indices[k] == i)
+ {
+ if (predicate(Values[k], otherData[i]))
+ {
+ return new Tuple(i, Values[k], otherData[i]);
+ }
+ k++;
+ }
+ else
+ {
+ if (predicate(Zero, otherData[i]))
+ {
+ return new Tuple(i, Zero, otherData[i]);
+ }
+ }
+ }
+ return null;
+ }
+
+ var sparseOther = other as SparseVectorStorage;
+ if (sparseOther != null)
+ {
+ int[] otherIndices = sparseOther.Indices;
+ TOther[] otherValues = sparseOther.Values;
+ int otherValueCount = sparseOther.ValueCount;
+ TOther otherZero = BuilderInstance.Matrix.Zero;
+
+ // Full Scan
+ int k = 0, otherk = 0;
+ if (zeros == Zeros.Include && ValueCount < Length && sparseOther.ValueCount < Length && predicate(Zero, otherZero))
+ {
+ for (int i = 0; i < Length; i++)
+ {
+ var left = k < ValueCount && Indices[k] == i ? Values[k++] : Zero;
+ var right = otherk < otherValueCount && otherIndices[otherk] == i ? otherValues[otherk++] : otherZero;
+ if (predicate(left, right))
+ {
+ return new Tuple(i, left, right);
+ }
+ }
+ return null;
+ }
+
+ // Sparse Scan
+ k = 0;
+ otherk = 0;
+ while (k < ValueCount || otherk < otherValueCount)
+ {
+ if (k == ValueCount || otherk < otherValueCount && Indices[k] > otherIndices[otherk])
+ {
+ if (predicate(Zero, otherValues[otherk++]))
+ {
+ return new Tuple(otherIndices[otherk - 1], Zero, otherValues[otherk - 1]);
+ }
+ }
+ else if (otherk == otherValueCount || Indices[k] < otherIndices[otherk])
+ {
+ if (predicate(Values[k++], otherZero))
+ {
+ return new Tuple(Indices[k - 1], Values[k - 1], otherZero);
+ }
+ }
+ else
+ {
+ if (predicate(Values[k++], otherValues[otherk++]))
+ {
+ return new Tuple(Indices[k - 1], Values[k - 1], otherValues[otherk - 1]);
+ }
+ }
+ }
+ return null;
+ }
+
+ // FALL BACK
+
+ return base.Find2Unchecked(other, predicate, zeros);
+ }
+
// FUNCTIONAL COMBINATORS
internal override void MapToUnchecked(VectorStorage target, Func f, Zeros zeros, ExistingData existingData)
diff --git a/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs
index 04077836..48f68bb6 100644
--- a/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs
+++ b/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs
@@ -98,22 +98,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
/// WARNING: This method is not thread safe. Use "lock" with it and be sure to avoid deadlocks.
public abstract void At(int index, T value);
- public virtual void Clear()
- {
- for (var i = 0; i < Length; i++)
- {
- At(i, Zero);
- }
- }
-
- public virtual void Clear(int index, int count)
- {
- for (var i = index; i < index + count; i++)
- {
- At(i, Zero);
- }
- }
-
///
/// Indicates whether the current object is equal to another object of the same type.
///
@@ -185,6 +169,24 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return hash;
}
+ // CLEARING
+
+ public virtual void Clear()
+ {
+ for (var i = 0; i < Length; i++)
+ {
+ At(i, Zero);
+ }
+ }
+
+ public virtual void Clear(int index, int count)
+ {
+ for (var i = index; i < index + count; i++)
+ {
+ At(i, Zero);
+ }
+ }
+
// VECTOR COPY
public void CopyTo(VectorStorage target, ExistingData existingData = ExistingData.Clear)
@@ -411,6 +413,52 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
+ // FIND
+
+ public virtual Tuple Find(Func predicate, Zeros zeros)
+ {
+ for (int i = 0; i < Length; i++)
+ {
+ var item = At(i);
+ if (predicate(item))
+ {
+ return new Tuple(i, item);
+ }
+ }
+ return null;
+ }
+
+ public Tuple Find2(VectorStorage other, Func predicate, Zeros zeros)
+ where TOther : struct, IEquatable, IFormattable
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Length != other.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ return Find2Unchecked(other, predicate, zeros);
+ }
+
+ internal virtual Tuple Find2Unchecked(VectorStorage other, Func predicate, Zeros zeros)
+ where TOther : struct, IEquatable, IFormattable
+ {
+ for (int i = 0; i < Length; i++)
+ {
+ var item = At(i);
+ var otherItem = other.At(i);
+ if (predicate(item, otherItem))
+ {
+ return new Tuple(i, item, otherItem);
+ }
+ }
+ return null;
+ }
+
// FUNCTIONAL COMBINATORS
public void MapTo(VectorStorage target, Func f,
diff --git a/src/Numerics/LinearAlgebra/Vector.cs b/src/Numerics/LinearAlgebra/Vector.cs
index d01e8675..1988103a 100644
--- a/src/Numerics/LinearAlgebra/Vector.cs
+++ b/src/Numerics/LinearAlgebra/Vector.cs
@@ -484,5 +484,62 @@ namespace MathNet.Numerics.LinearAlgebra
{
return Storage.Fold2(other.Storage, f, state, zeros);
}
+
+ ///
+ /// Returns a tuple with the index and value of the first element satisfying a predicate, or null if none is found.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
+ public Tuple Find(Func predicate, Zeros zeros = Zeros.AllowSkip)
+ {
+ return Storage.Find(predicate, zeros);
+ }
+
+ ///
+ /// Returns a tuple with the index and values of the first element pair of two vectors of the same size satisfying a predicate, or null if none is found.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
+ public Tuple Find2(Func predicate, Vector other, Zeros zeros = Zeros.AllowSkip)
+ where TOther : struct, IEquatable, IFormattable
+ {
+ return Storage.Find2(other.Storage, predicate, zeros);
+ }
+
+ ///
+ /// Returns true if at least one element satisfies a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
+ public bool Exists(Func predicate, Zeros zeros = Zeros.AllowSkip)
+ {
+ return Storage.Find(predicate, zeros) != null;
+ }
+
+ ///
+ /// Returns true if at least one element pairs of two vectors of the same size satisfies a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
+ public bool Exists2(Func predicate, Vector other, Zeros zeros = Zeros.AllowSkip)
+ where TOther : struct, IEquatable, IFormattable
+ {
+ return Storage.Find2(other.Storage, predicate, zeros) != null;
+ }
+
+ ///
+ /// Returns true if all elements satisfy a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
+ public bool ForAll(Func predicate, Zeros zeros = Zeros.AllowSkip)
+ {
+ return Storage.Find(x => !predicate(x), zeros) == null;
+ }
+
+ ///
+ /// Returns true if all element pairs of two vectors of the same size satisfy a predicate.
+ /// Zero elements may be skipped on sparse data structures if allowed (default).
+ ///
+ public bool ForAll2(Func predicate, Vector other, Zeros zeros = Zeros.AllowSkip)
+ where TOther : struct, IEquatable, IFormattable
+ {
+ return Storage.Find2(other.Storage, (x, y) => !predicate(x, y), zeros) == null;
+ }
}
}