Browse Source

More value tuples

dependabot/nuget/NUnit3TestAdapter-4.2.0
Christoph Ruegg 5 years ago
parent
commit
834a2d6425
  1. 3
      .paket/Paket.Restore.targets
  2. 8
      src/Data.Text/MatrixMarketReader.cs
  3. 8
      src/FSharp/LinearAlgebra.Matrix.fs
  4. 4
      src/FSharp/LinearAlgebra.Vector.fs
  5. 10
      src/Numerics.Tests/GenerateTests.cs
  6. 41
      src/Numerics/Generate.cs
  7. 44
      src/Numerics/LinearAlgebra/Builder.cs
  8. 11
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  9. 11
      src/Numerics/LinearAlgebra/Complex/DenseVector.cs
  10. 11
      src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
  11. 11
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  12. 11
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  13. 11
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  14. 11
      src/Numerics/LinearAlgebra/Complex32/DenseVector.cs
  15. 11
      src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs
  16. 11
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  17. 11
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  18. 24
      src/Numerics/LinearAlgebra/CreateMatrix.cs
  19. 24
      src/Numerics/LinearAlgebra/CreateVector.cs
  20. 11
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  21. 11
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  22. 11
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  23. 11
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  24. 11
      src/Numerics/LinearAlgebra/Double/SparseVector.cs
  25. 20
      src/Numerics/LinearAlgebra/Matrix.cs
  26. 11
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  27. 11
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  28. 11
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  29. 11
      src/Numerics/LinearAlgebra/Single/SparseMatrix.cs
  30. 11
      src/Numerics/LinearAlgebra/Single/SparseVector.cs
  31. 28
      src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs
  32. 27
      src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs
  33. 29
      src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs
  34. 8
      src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
  35. 58
      src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
  36. 48
      src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs
  37. 8
      src/Numerics/LinearAlgebra/Storage/VectorStorage.cs
  38. 4
      src/Numerics/LinearAlgebra/Vector.cs
  39. 51
      src/Numerics/LinearRegression/MultipleRegression.cs
  40. 16
      src/Numerics/LinearRegression/SimpleRegression.cs
  41. 34
      src/Numerics/LinearRegression/Util.cs
  42. 24
      src/Numerics/LinearRegression/WeightedRegression.cs
  43. 8
      src/Numerics/Optimization/LevenbergMarquardtMinimizer.cs
  44. 4
      src/Numerics/Optimization/NonlinearMinimizerBase.cs
  45. 8
      src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs

3
.paket/Paket.Restore.targets

@ -359,7 +359,8 @@
NuspecProperties="$(NuspecProperties)"
PackageLicenseFile="$(PackageLicenseFile)"
PackageLicenseExpression="$(PackageLicenseExpression)"
PackageLicenseExpressionVersion="$(PackageLicenseExpressionVersion)" />
PackageLicenseExpressionVersion="$(PackageLicenseExpressionVersion)"
NoDefaultExcludes="$(NoDefaultExcludes)" />
<PackTask Condition="$(UseMSBuild15_9_Pack)"
PackItem="$(PackProjectInputFile)"

8
src/Data.Text/MatrixMarketReader.cs

@ -133,7 +133,7 @@ namespace MathNet.Numerics.Data.Text
if (sparse)
{
var indexed = ReadTokenLines(reader).Select(tokens => new Tuple<int, int, T>(int.Parse(tokens[0]) - 1, int.Parse(tokens[1]) - 1, parse(2, tokens)));
var indexed = ReadTokenLines(reader).Select(tokens => (int.Parse(tokens[0]) - 1, int.Parse(tokens[1]) - 1, parse(2, tokens)));
return Matrix<T>.Build.SparseOfIndexed(rows, cols, symmetry == MatrixMarketSymmetry.General ? indexed : ExpandSparse(symmetry, indexed));
}
@ -207,7 +207,7 @@ namespace MathNet.Numerics.Data.Text
if (sparse)
{
var indexedSeq = ReadTokenLines(reader).Select(tokens => new Tuple<int, T>(int.Parse(tokens[0]) - 1, parse(1, tokens)));
var indexedSeq = ReadTokenLines(reader).Select(tokens => (int.Parse(tokens[0]) - 1, parse(1, tokens)));
return Vector<T>.Build.SparseOfIndexed(length, indexedSeq);
}
@ -326,7 +326,7 @@ namespace MathNet.Numerics.Data.Text
}
}
static IEnumerable<Tuple<int, int, T>> ExpandSparse<T>(MatrixMarketSymmetry symmetry, IEnumerable<Tuple<int, int, T>> indexedValues)
static IEnumerable<(int, int, T)> ExpandSparse<T>(MatrixMarketSymmetry symmetry, IEnumerable<(int, int, T)> indexedValues)
{
var map = CreateSymmetryMap<T>(symmetry);
foreach (var x in indexedValues)
@ -334,7 +334,7 @@ namespace MathNet.Numerics.Data.Text
yield return x;
if (x.Item1 != x.Item2)
{
yield return new Tuple<int, int, T>(x.Item2, x.Item1, map(x.Item3));
yield return (x.Item2, x.Item1, map(x.Item3));
}
}
}

8
src/FSharp/LinearAlgebra.Matrix.fs

@ -52,25 +52,25 @@ module Matrix =
let inline toSeq (m: #Matrix<_>) = m.Enumerate(Zeros.Include)
/// Transform a matrix into an indexed sequence.
let inline toSeqi (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include)
let inline toSeqi (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.map (fun t -> t.ToTuple())
/// Transform a matrix into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqSkipZeros (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip)
/// Transform a matrix into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqiSkipZeros (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip)
let inline toSeqiSkipZeros (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.map (fun t -> t.ToTuple())
/// Transform a matrix into a column sequence.
let inline toColSeq (m: #Matrix<_>) = m.EnumerateColumns()
/// Transform a matrix into an indexed column sequence.
let inline toColSeqi (m: #Matrix<_>) = m.EnumerateColumnsIndexed()
let inline toColSeqi (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> Seq.map (fun t -> t.ToTuple())
/// Transform a matrix into a row sequence.
let inline toRowSeq (m: #Matrix<_>) = m.EnumerateRows()
/// Transform a matrix into an indexed row sequence.
let inline toRowSeqi (m: #Matrix<_>) = m.EnumerateRowsIndexed()
let inline toRowSeqi (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> Seq.map (fun t -> t.ToTuple())
/// Applies a function to all elements of the matrix.

4
src/FSharp/LinearAlgebra.Vector.fs

@ -49,13 +49,13 @@ module Vector =
let inline toSeq (v: #Vector<_>) = v.Enumerate(Zeros.Include)
/// Transform a vector into an indexed sequence.
let inline toSeqi (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include)
let inline toSeqi (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> Seq.map (fun t -> t.ToTuple())
/// Transform a vector into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqSkipZeros (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip)
/// Transform a vector into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqiSkipZeros (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip)
let inline toSeqiSkipZeros (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.map (fun t -> t.ToTuple())
/// Applies a function to all elements of the vector.

10
src/Numerics.Tests/GenerateTests.cs

@ -222,8 +222,8 @@ namespace MathNet.Numerics.UnitTests
public void UnfoldConsistentWithSequence()
{
Assert.That(
Generate.UnfoldSequence((s => new Tuple<int, int>(s + 1, s + 1)), 0).Take(250).ToArray(),
Is.EqualTo(Generate.Unfold(250, (s => new Tuple<int, int>(s + 1, s + 1)), 0)).AsCollection);
Generate.UnfoldSequence((s => (s + 1, s + 1)), 0).Take(250).ToArray(),
Is.EqualTo(Generate.Unfold(250, (s => (s + 1, s + 1)), 0)).AsCollection);
}
[Test]
@ -239,11 +239,11 @@ namespace MathNet.Numerics.UnitTests
{
Assert.That(
Generate.FibonacciSequence().Take(250).ToArray(),
Is.EqualTo(new[] { BigInteger.Zero, BigInteger.One }.Concat(Generate.Unfold(248, (s =>
Is.EqualTo(new[] { BigInteger.Zero, BigInteger.One }.Concat(Generate.Unfold(248, s =>
{
var z = s.Item1 + s.Item2;
return new Tuple<BigInteger, Tuple<BigInteger, BigInteger>>(z, new Tuple<BigInteger, BigInteger>(s.Item2, z));
}), new Tuple<BigInteger, BigInteger>(BigInteger.Zero, BigInteger.One)))).AsCollection);
return (z, (s.Item2, z));
}, (BigInteger.Zero, BigInteger.One)))).AsCollection);
}
}
}

41
src/Numerics/Generate.cs

@ -774,9 +774,25 @@ namespace MathNet.Numerics
var data = new T[length];
for (int i = 0; i < data.Length; i++)
{
Tuple<T, TState> next = f(state);
data[i] = next.Item1;
state = next.Item2;
(data[i], state) = f(state);
}
return data;
}
/// <summary>
/// Generate samples generated by the given computation.
/// </summary>
public static T[] Unfold<T, TState>(int length, Func<TState, (T, TState)> f, TState state)
{
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
var data = new T[length];
for (int i = 0; i < data.Length; i++)
{
(data[i], state) = f(state);
}
return data;
}
@ -788,9 +804,22 @@ namespace MathNet.Numerics
{
while (true)
{
Tuple<T, TState> next = f(state);
state = next.Item2;
yield return next.Item1;
var (item, nextState) = f(state);
state = nextState;
yield return item;
}
}
/// <summary>
/// Generate an infinite sequence generated by the given computation.
/// </summary>
public static IEnumerable<T> UnfoldSequence<T, TState>(Func<TState, (T, TState)> f, TState state)
{
while (true)
{
var (item, nextState) = f(state);
state = nextState;
yield return item;
}
}

44
src/Numerics/LinearAlgebra/Builder.cs

@ -565,6 +565,17 @@ namespace MathNet.Numerics.LinearAlgebra
return Dense(DenseColumnMajorMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public Matrix<T> DenseOfIndexed(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
{
return Dense(DenseColumnMajorMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column).
@ -911,6 +922,17 @@ namespace MathNet.Numerics.LinearAlgebra
return Sparse(SparseCompressedRowMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public Matrix<T> SparseOfIndexed(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
{
return Sparse(SparseCompressedRowMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row).
@ -1537,6 +1559,17 @@ namespace MathNet.Numerics.LinearAlgebra
return Dense(DenseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public Vector<T> DenseOfIndexed(int length, IEnumerable<(int, T)> enumerable)
{
return Dense(DenseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector straight from an initialized vector storage instance.
/// The storage is used directly without copying.
@ -1611,6 +1644,17 @@ namespace MathNet.Numerics.LinearAlgebra
{
return Sparse(SparseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public Vector<T> SparseOfIndexed(int length, IEnumerable<(int, T)> enumerable)
{
return Sparse(SparseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
}
}
internal static class BuilderInstance<T> where T : struct, IEquatable<T>, IFormattable

11
src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs

@ -145,6 +145,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Complex/DenseVector.cs

@ -131,6 +131,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DenseVector(DenseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex)> enumerable)
{
return new DenseVector(DenseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector and initialize each value using the provided value.
/// </summary>

11
src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs

@ -148,6 +148,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DiagonalMatrix(DiagonalMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, Complex)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

@ -118,6 +118,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row).

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

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new SparseVector(SparseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex)> enumerable)
{
return new SparseVector(SparseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector and initialize each value using the provided value.
/// </summary>

11
src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs

@ -145,6 +145,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex32)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Complex32/DenseVector.cs

@ -131,6 +131,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DenseVector(DenseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex32)> enumerable)
{
return new DenseVector(DenseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector and initialize each value using the provided value.
/// </summary>

11
src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs

@ -148,6 +148,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DiagonalMatrix(DiagonalMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, Complex32)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

@ -118,6 +118,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex32)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row).

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

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new SparseVector(SparseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex32)> enumerable)
{
return new SparseVector(SparseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector and initialize each value using the provided value.
/// </summary>

24
src/Numerics/LinearAlgebra/CreateMatrix.cs

@ -281,6 +281,18 @@ namespace MathNet.Numerics.LinearAlgebra
return Matrix<T>.Build.DenseOfIndexed(rows, columns, enumerable);
}
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static Matrix<T> DenseOfIndexed<T>(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Matrix<T>.Build.DenseOfIndexed(rows, columns, enumerable);
}
/// <summary>
/// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column).
@ -605,6 +617,18 @@ namespace MathNet.Numerics.LinearAlgebra
return Matrix<T>.Build.SparseOfIndexed(rows, columns, enumerable);
}
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static Matrix<T> SparseOfIndexed<T>(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Matrix<T>.Build.SparseOfIndexed(rows, columns, enumerable);
}
/// <summary>
/// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row).

24
src/Numerics/LinearAlgebra/CreateVector.cs

@ -224,6 +224,18 @@ namespace MathNet.Numerics.LinearAlgebra
return Vector<T>.Build.DenseOfIndexed(length, enumerable);
}
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static Vector<T> DenseOfIndexed<T>(int length, IEnumerable<(int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Vector<T>.Build.DenseOfIndexed(length, enumerable);
}
/// <summary>
/// Create a new sparse vector straight from an initialized vector storage instance.
/// The storage is used directly without copying.
@ -308,5 +320,17 @@ namespace MathNet.Numerics.LinearAlgebra
{
return Vector<T>.Build.SparseOfIndexed(length, enumerable);
}
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static Vector<T> SparseOfIndexed<T>(int length, IEnumerable<(int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Vector<T>.Build.SparseOfIndexed(length, enumerable);
}
}
}

11
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -143,6 +143,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DenseMatrix(DenseColumnMajorMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, double)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -130,6 +130,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DenseVector(DenseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int,double)> enumerable)
{
return new DenseVector(DenseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector and initialize each value using the provided value.
/// </summary>

11
src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs

@ -146,6 +146,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DiagonalMatrix(DiagonalMatrixStorage<double>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, double)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<double>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

@ -116,6 +116,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new SparseMatrix(SparseCompressedRowMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, double)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row).

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

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new SparseVector(SparseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, double)> enumerable)
{
return new SparseVector(SparseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector and initialize each value using the provided value.
/// </summary>

20
src/Numerics/LinearAlgebra/Matrix.cs

@ -1471,7 +1471,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the third value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero.
/// </remarks>
public IEnumerable<Tuple<int, int, T>> EnumerateIndexed()
public IEnumerable<(int, int, T)> EnumerateIndexed()
{
return Storage.EnumerateIndexed();
}
@ -1484,7 +1484,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the third value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero.
/// </remarks>
public IEnumerable<Tuple<int, int, T>> EnumerateIndexed(Zeros zeros = Zeros.Include)
public IEnumerable<(int, int, T)> EnumerateIndexed(Zeros zeros = Zeros.Include)
{
switch (zeros)
{
@ -1527,11 +1527,11 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the column index
/// and the second value being the value of the column at that index.
/// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateColumnsIndexed()
public IEnumerable<(int, Vector<T>)> EnumerateColumnsIndexed()
{
for (var i = 0; i < ColumnCount; i++)
{
yield return new Tuple<int, Vector<T>>(i, Column(i));
yield return (i, Column(i));
}
}
@ -1544,12 +1544,12 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the column index
/// and the second value being the value of the column at that index.
/// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateColumnsIndexed(int index, int length)
public IEnumerable<(int, Vector<T>)> EnumerateColumnsIndexed(int index, int length)
{
var maxIndex = Math.Min(index + length, ColumnCount);
for (var i = Math.Max(index, 0); i < maxIndex; i++)
{
yield return new Tuple<int, Vector<T>>(i, Column(i));
yield return (i, Column(i));
}
}
@ -1585,11 +1585,11 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the row index
/// and the second value being the value of the row at that index.
/// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateRowsIndexed()
public IEnumerable<(int, Vector<T>)> EnumerateRowsIndexed()
{
for (var i = 0; i < RowCount; i++)
{
yield return new Tuple<int, Vector<T>>(i, Row(i));
yield return (i, Row(i));
}
}
@ -1602,12 +1602,12 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the row index
/// and the second value being the value of the row at that index.
/// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateRowsIndexed(int index, int length)
public IEnumerable<(int, Vector<T>)> EnumerateRowsIndexed(int index, int length)
{
var maxIndex = Math.Min(index + length, RowCount);
for (var i = Math.Max(index, 0); i < maxIndex; i++)
{
yield return new Tuple<int, Vector<T>>(i, Row(i));
yield return (i, Row(i));
}
}

11
src/Numerics/LinearAlgebra/Single/DenseMatrix.cs

@ -143,6 +143,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DenseMatrix(DenseColumnMajorMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, float)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Single/DenseVector.cs

@ -131,6 +131,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DenseVector(DenseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int, float)> enumerable)
{
return new DenseVector(DenseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new dense vector and initialize each value using the provided value.
/// </summary>

11
src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs

@ -146,6 +146,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DiagonalMatrix(DiagonalMatrixStorage<float>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, float)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<float>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

@ -117,6 +117,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new SparseMatrix(SparseCompressedRowMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, float)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary>
/// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row).

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

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new SparseVector(SparseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, float)> enumerable)
{
return new SparseVector(SparseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
}
/// <summary>
/// Create a new sparse vector and initialize each value using the provided value.
/// </summary>

28
src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs

@ -329,9 +329,19 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
public static DenseColumnMajorMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<Tuple<int, int, T>> data)
{
var array = new T[rows*columns];
foreach (var item in data)
foreach (var (i,j,x) in data)
{
array[(item.Item2*rows) + item.Item1] = item.Item3;
array[j * rows + i] = x;
}
return new DenseColumnMajorMatrixStorage<T>(rows, columns, array);
}
public static DenseColumnMajorMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<(int, int, T)> data)
{
var array = new T[rows*columns];
foreach (var (i,j,x) in data)
{
array[j * rows + i] = x;
}
return new DenseColumnMajorMatrixStorage<T>(rows, columns, array);
}
@ -669,14 +679,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data;
}
public override IEnumerable<Tuple<int, int, T>> EnumerateIndexed()
public override IEnumerable<(int, int, T)> EnumerateIndexed()
{
int index = 0;
for (int j = 0; j < ColumnCount; j++)
{
for (int i = 0; i < RowCount; i++)
{
yield return new Tuple<int, int, T>(i, j, Data[index]);
yield return (i, j, Data[index]);
index++;
}
}
@ -687,7 +697,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data.Where(x => !Zero.Equals(x));
}
public override IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed()
public override IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{
int index = 0;
for (int j = 0; j < ColumnCount; j++)
@ -697,7 +707,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
var x = Data[index];
if (!Zero.Equals(x))
{
yield return new Tuple<int, int, T>(i, j, x);
yield return (i, j, x);
}
index++;
}
@ -712,8 +722,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
{
if (predicate(Data[i]))
{
int row, column;
RowColumnAtIndex(i, out row, out column);
RowColumnAtIndex(i, out int row, out int column);
return new Tuple<int, int, T>(row, column, Data[i]);
}
}
@ -729,8 +738,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
{
if (predicate(Data[i], otherData[i]))
{
int row, column;
RowColumnAtIndex(i, out row, out column);
RowColumnAtIndex(i, out int row, out int column);
return new Tuple<int, int, T, TOther>(row, column, Data[i], otherData[i]);
}

27
src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs

@ -171,9 +171,24 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
var array = new T[length];
foreach (var item in data)
foreach (var (index, value) in data)
{
array[item.Item1] = item.Item2;
array[index] = value;
}
return new DenseVectorStorage<T>(array.Length, array);
}
public static DenseVectorStorage<T> OfIndexedEnumerable(int length, IEnumerable<(int, T)> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var array = new T[length];
foreach (var (index, value) in data)
{
array[index] = value;
}
return new DenseVectorStorage<T>(array.Length, array);
}
@ -338,9 +353,9 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data;
}
public override IEnumerable<Tuple<int, T>> EnumerateIndexed()
public override IEnumerable<(int, T)> EnumerateIndexed()
{
return Data.Select((t, i) => new Tuple<int, T>(i, t));
return Data.Select((t, i) => (i, t));
}
public override IEnumerable<T> EnumerateNonZero()
@ -348,13 +363,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data.Where(x => !Zero.Equals(x));
}
public override IEnumerable<Tuple<int, T>> EnumerateNonZeroIndexed()
public override IEnumerable<(int, T)> EnumerateNonZeroIndexed()
{
for (var i = 0; i < Data.Length; i++)
{
if (!Zero.Equals(Data[i]))
{
yield return new Tuple<int, T>(i, Data[i]);
yield return (i, Data[i]);
}
}
}

29
src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs

@ -237,9 +237,24 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
var storage = new DiagonalMatrixStorage<T>(rows, columns);
foreach (var item in data)
foreach (var (i,x) in data)
{
storage.Data[item.Item1] = item.Item2;
storage.Data[i] = x;
}
return storage;
}
public static DiagonalMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<(int, T)> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var storage = new DiagonalMatrixStorage<T>(rows, columns);
foreach (var (i,x) in data)
{
storage.Data[i] = x;
}
return storage;
}
@ -559,16 +574,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public override IEnumerable<Tuple<int, int, T>> EnumerateIndexed()
public override IEnumerable<(int, int, T)> EnumerateIndexed()
{
for (int j = 0; j < ColumnCount; j++)
{
for (int i = 0; i < RowCount; i++)
{
// PERF: consider to break up loop to avoid branching
yield return i == j
? new Tuple<int, int, T>(i, i, Data[i])
: new Tuple<int, int, T>(i, j, Zero);
yield return (i, j, i == j ? Data[i] : Zero);
}
}
}
@ -578,13 +591,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data.Where(x => !Zero.Equals(x));
}
public override IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed()
public override IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{
for (int i = 0; i < Data.Length; i++)
{
if (!Zero.Equals(Data[i]))
{
yield return new Tuple<int, int, T>(i, i, Data[i]);
yield return (i, i, Data[i]);
}
}
}

8
src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs

@ -623,13 +623,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public virtual IEnumerable<Tuple<int, int, T>> EnumerateIndexed()
public virtual IEnumerable<(int, int, T)> EnumerateIndexed()
{
for (int i = 0; i < RowCount; i++)
{
for (int j = 0; j < ColumnCount; j++)
{
yield return new Tuple<int, int, T>(i, j, At(i, j));
yield return (i, j, At(i, j));
}
}
}
@ -649,7 +649,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public virtual IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed()
public virtual IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{
for (int i = 0; i < RowCount; i++)
{
@ -658,7 +658,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
var x = At(i, j);
if (!Zero.Equals(x))
{
yield return new Tuple<int, int, T>(i, j, x);
yield return (i, j, x);
}
}
}

58
src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs

@ -765,12 +765,52 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
public static SparseCompressedRowMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<Tuple<int, int, T>> data)
{
var trows = new List<Tuple<int, T>>[rows];
foreach (var item in data)
foreach (var (i,j,x) in data)
{
if (!Zero.Equals(item.Item3))
if (!Zero.Equals(x))
{
var row = trows[i] ?? (trows[i] = new List<Tuple<int, T>>());
row.Add(new Tuple<int, T>(j, x));
}
}
var storage = new SparseCompressedRowMatrixStorage<T>(rows, columns);
var rowPointers = storage.RowPointers;
var columnIndices = new List<int>();
var values = new List<T>();
int index = 0;
for (int row = 0; row < rows; row++)
{
rowPointers[row] = index;
var trow = trows[row];
if (trow != null)
{
trow.Sort();
foreach (var item in trow)
{
values.Add(item.Item2);
columnIndices.Add(item.Item1);
index++;
}
}
}
rowPointers[rows] = values.Count;
storage.ColumnIndices = columnIndices.ToArray();
storage.Values = values.ToArray();
return storage;
}
public static SparseCompressedRowMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<(int, int, T)> data)
{
var trows = new List<Tuple<int, T>>[rows];
foreach (var (i,j,x) in data)
{
if (!Zero.Equals(x))
{
var row = trows[item.Item1] ?? (trows[item.Item1] = new List<Tuple<int, T>>());
row.Add(new Tuple<int, T>(item.Item2, item.Item3));
var row = trows[i] ?? (trows[i] = new List<Tuple<int, T>>());
row.Add(new Tuple<int, T>(j, x));
}
}
@ -1653,16 +1693,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public override IEnumerable<Tuple<int, int, T>> EnumerateIndexed()
public override IEnumerable<(int, int, T)> EnumerateIndexed()
{
int k = 0;
for (int row = 0; row < RowCount; row++)
{
for (int col = 0; col < ColumnCount; col++)
{
yield return k < RowPointers[row + 1] && ColumnIndices[k] == col
? new Tuple<int, int, T>(row, col, Values[k++])
: new Tuple<int, int, T>(row, col, Zero);
yield return (row, col, k < RowPointers[row + 1] && ColumnIndices[k] == col ? Values[k++] : Zero);
}
}
}
@ -1672,7 +1710,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Values.Take(ValueCount).Where(x => !Zero.Equals(x));
}
public override IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed()
public override IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{
for (int row = 0; row < RowCount; row++)
{
@ -1682,7 +1720,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
{
if (!Zero.Equals(Values[j]))
{
yield return new Tuple<int, int, T>(row, ColumnIndices[j], Values[j]);
yield return (row, ColumnIndices[j], Values[j]);
}
}
}

48
src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs

@ -397,12 +397,42 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
var indices = new List<int>();
var values = new List<T>();
foreach (var item in data)
foreach (var (i, x) in data)
{
if (!Zero.Equals(item.Item2))
if (!Zero.Equals(x))
{
values.Add(item.Item2);
indices.Add(item.Item1);
values.Add(x);
indices.Add(i);
}
}
var indicesArray = indices.ToArray();
var valuesArray = values.ToArray();
Sorting.Sort(indicesArray, valuesArray);
return new SparseVectorStorage<T>(length)
{
Indices = indicesArray,
Values = valuesArray,
ValueCount = values.Count
};
}
public static SparseVectorStorage<T> OfIndexedEnumerable(int length, IEnumerable<(int, T)> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var indices = new List<int>();
var values = new List<T>();
foreach (var (i, x) in data)
{
if (!Zero.Equals(x))
{
values.Add(x);
indices.Add(i);
}
}
@ -631,14 +661,12 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public override IEnumerable<Tuple<int, T>> EnumerateIndexed()
public override IEnumerable<(int, T)> EnumerateIndexed()
{
int k = 0;
for (int i = 0; i < Length; i++)
{
yield return k < ValueCount && Indices[k] == i
? new Tuple<int, T>(i, Values[k++])
: new Tuple<int, T>(i, Zero);
yield return (i, k < ValueCount && Indices[k] == i ? Values[k++] : Zero);
}
}
@ -647,13 +675,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Values.Take(ValueCount).Where(x => !Zero.Equals(x));
}
public override IEnumerable<Tuple<int, T>> EnumerateNonZeroIndexed()
public override IEnumerable<(int, T)> EnumerateNonZeroIndexed()
{
for (var i = 0; i < ValueCount; i++)
{
if (!Zero.Equals(Values[i]))
{
yield return new Tuple<int, T>(Indices[i], Values[i]);
yield return (Indices[i], Values[i]);
}
}
}

8
src/Numerics/LinearAlgebra/Storage/VectorStorage.cs

@ -400,11 +400,11 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public virtual IEnumerable<Tuple<int, T>> EnumerateIndexed()
public virtual IEnumerable<(int, T)> EnumerateIndexed()
{
for (var i = 0; i < Length; i++)
{
yield return new Tuple<int, T>(i, At(i));
yield return (i, At(i));
}
}
@ -420,14 +420,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
public virtual IEnumerable<Tuple<int, T>> EnumerateNonZeroIndexed()
public virtual IEnumerable<(int, T)> EnumerateNonZeroIndexed()
{
for (var i = 0; i < Length; i++)
{
var x = At(i);
if (!Zero.Equals(x))
{
yield return new Tuple<int, T>(i, x);
yield return (i, x);
}
}
}

4
src/Numerics/LinearAlgebra/Vector.cs

@ -323,7 +323,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the second value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero.
/// </remarks>
public IEnumerable<Tuple<int, T>> EnumerateIndexed()
public IEnumerable<(int, T)> EnumerateIndexed()
{
return Storage.EnumerateIndexed();
}
@ -336,7 +336,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the second value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero.
/// </remarks>
public IEnumerable<Tuple<int, T>> EnumerateIndexed(Zeros zeros = Zeros.Include)
public IEnumerable<(int, T)> EnumerateIndexed(Zeros zeros = Zeros.Include)
{
switch (zeros)
{

51
src/Numerics/LinearRegression/MultipleRegression.cs

@ -208,8 +208,21 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] NormalEquations<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return NormalEquations(xy.Item1, xy.Item2, intercept);
var (u, v) = samples.UnpackSinglePass();
return NormalEquations(u, v, intercept);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses the cholesky decomposition of the normal equations.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] NormalEquations<T>(IEnumerable<(T[], T)> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return NormalEquations(u, v, intercept);
}
/// <summary>
@ -294,8 +307,21 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] QR<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return QR(xy.Item1, xy.Item2, intercept);
var (u, v) = samples.UnpackSinglePass();
return QR(u, v, intercept);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses an orthogonal decomposition and is therefore more numerically stable than the normal equations but also slower.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] QR<T>(IEnumerable<(T[], T)> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return QR(u, v, intercept);
}
/// <summary>
@ -380,8 +406,21 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] Svd<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return Svd(xy.Item1, xy.Item2, intercept);
var (u, v) = samples.UnpackSinglePass();
return Svd(u, v, intercept);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses a singular value decomposition and is therefore more numerically stable (especially if ill-conditioned) than the normal equations or QR but also slower.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] Svd<T>(IEnumerable<(T[], T)> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return Svd(u, v, intercept);
}
}
}

16
src/Numerics/LinearRegression/SimpleRegression.cs

@ -87,8 +87,20 @@ namespace MathNet.Numerics.LinearRegression
/// <param name="samples">Predictor-Response samples as tuples</param>
public static (double A, double B) Fit(IEnumerable<Tuple<double, double>> samples)
{
var xy = samples.UnpackSinglePass();
return Fit(xy.Item1, xy.Item2);
var (u, v) = samples.UnpackSinglePass();
return Fit(u, v);
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as (a, b) tuple,
/// where a is the intercept and b the slope.
/// </summary>
/// <param name="samples">Predictor-Response samples as tuples</param>
public static (double A, double B) Fit(IEnumerable<(double, double)> samples)
{
var (u, v) = samples.UnpackSinglePass();
return Fit(u, v);
}
/// <summary>

34
src/Numerics/LinearRegression/Util.cs

@ -2,9 +2,9 @@
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
//
// Copyright (c) 2009-2013 Math.NET
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -13,10 +13,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -34,18 +34,32 @@ namespace MathNet.Numerics.LinearRegression
{
internal static class Util
{
public static Tuple<TU[], TV[]> UnpackSinglePass<TU, TV>(this IEnumerable<Tuple<TU, TV>> samples)
public static (TU[] U, TV[] V) UnpackSinglePass<TU, TV>(this IEnumerable<Tuple<TU, TV>> samples)
{
var u = new List<TU>();
var v = new List<TV>();
var ux = new List<TU>();
var vx = new List<TV>();
foreach (var tuple in samples)
{
u.Add(tuple.Item1);
v.Add(tuple.Item2);
ux.Add(tuple.Item1);
vx.Add(tuple.Item2);
}
return new Tuple<TU[], TV[]>(u.ToArray(), v.ToArray());
return (ux.ToArray(), vx.ToArray());
}
public static (TU[] U, TV[] V) UnpackSinglePass<TU, TV>(this IEnumerable<(TU, TV)> samples)
{
var ux = new List<TU>();
var vx = new List<TV>();
foreach (var (u, v) in samples)
{
ux.Add(u);
vx.Add(v);
}
return (ux.ToArray(), vx.ToArray());
}
}
}

24
src/Numerics/LinearRegression/WeightedRegression.cs

@ -2,9 +2,9 @@
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
//
// Copyright (c) 2009-2013 Math.NET
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -13,10 +13,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -85,8 +85,20 @@ namespace MathNet.Numerics.LinearRegression
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
public static T[] Weighted<T>(IEnumerable<Tuple<T[], T>> samples, T[] weights, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return Weighted(xy.Item1, xy.Item2, weights, intercept);
var (u, v) = samples.UnpackSinglePass();
return Weighted(u, v, weights, intercept);
}
/// <summary>
/// Weighted Linear Regression using normal equations.
/// </summary>
/// <param name="samples">List of sample vectors (predictor) together with their response.</param>
/// <param name="weights">List of weights, one for each sample.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
public static T[] Weighted<T>(IEnumerable<(T[], T)> samples, T[] weights, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return Weighted(u, v, weights, intercept);
}
/// <summary>

8
src/Numerics/Optimization/LevenbergMarquardtMinimizer.cs

@ -129,9 +129,7 @@ namespace MathNet.Numerics.Optimization
}
// Evaluate gradient and Hessian
var jac = EvaluateJacobian(objective, P);
var Gradient = jac.Item1; // objective.Gradient;
var Hessian = jac.Item2; // objective.Hessian;
var (Gradient, Hessian) = EvaluateJacobian(objective, P);
var diagonalOfHessian = Hessian.Diagonal(); // diag(H)
// if ||g||oo <= gtol, found and stop
@ -190,9 +188,7 @@ namespace MathNet.Numerics.Optimization
RSS = RSSnew;
// update gradient and Hessian
jac = EvaluateJacobian(objective, P);
Gradient = jac.Item1; // objective.Gradient;
Hessian = jac.Item2; // objective.Hessian;
(Gradient, Hessian) = EvaluateJacobian(objective, P);
diagonalOfHessian = Hessian.Diagonal();
// if ||g||_oo <= gtol, found and stop

4
src/Numerics/Optimization/NonlinearMinimizerBase.cs

@ -100,7 +100,7 @@ namespace MathNet.Numerics.Optimization
return objective.Value;
}
protected Tuple<Vector<double>, Matrix<double>> EvaluateJacobian(IObjectiveModel objective, Vector<double> Pint)
protected (Vector<double> Gradient, Matrix<double> Hessian) EvaluateJacobian(IObjectiveModel objective, Vector<double> Pint)
{
var gradient = objective.Gradient;
var hessian = objective.Hessian;
@ -123,7 +123,7 @@ namespace MathNet.Numerics.Optimization
}
}
return new Tuple<Vector<double>, Matrix<double>>(gradient, hessian);
return (gradient, hessian);
}
#region Projection of Parameters

8
src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs

@ -137,9 +137,7 @@ namespace MathNet.Numerics.Optimization.TrustRegion
}
// evaluate projected gradient and Hessian
var jac = EvaluateJacobian(objective, P);
var Gradient = jac.Item1; // objective.Gradient;
var Hessian = jac.Item2; // objective.Hessian;
var (Gradient, Hessian) = EvaluateJacobian(objective, P);
// if ||g||_oo <= gtol, found and stop
if (Gradient.InfinityNorm() <= gradientTolerance)
@ -213,9 +211,7 @@ namespace MathNet.Numerics.Optimization.TrustRegion
RSS = RSSnew;
// evaluate projected gradient and Hessian
jac = EvaluateJacobian(objective, P);
Gradient = jac.Item1; // objective.Gradient;
Hessian = jac.Item2; // objective.Hessian;
(Gradient, Hessian) = EvaluateJacobian(objective, P);
// if ||g||_oo <= gtol, found and stop
if (Gradient.InfinityNorm() <= gradientTolerance)

Loading…
Cancel
Save