diff --git a/CSparse/Converter.cs b/CSparse/Converter.cs index 131cb91..dec3661 100644 --- a/CSparse/Converter.cs +++ b/CSparse/Converter.cs @@ -289,5 +289,25 @@ public static CoordinateStorage FromEnumerable(IEnumerable + /// Convert a row major array to coordinate storage. + /// + /// Enumerates the entries of a matrix with value tuples. + /// Number of rows. + /// Number of columns. + /// Coordinate storage. + public static CoordinateStorage FromEnumerable(IEnumerable<(int row, int column, T value)> enumerable, int rowCount, int columnCount) + where T : struct, IEquatable, IFormattable + { + var storage = new CoordinateStorage(rowCount, columnCount, Math.Max(rowCount, columnCount)); + + foreach (var item in enumerable) + { + storage.At(item.row, item.column, item.value); + } + + return storage; + } } } diff --git a/CSparse/Matrix.cs b/CSparse/Matrix.cs index 907254e..aafcda9 100644 --- a/CSparse/Matrix.cs +++ b/CSparse/Matrix.cs @@ -132,9 +132,18 @@ protected Matrix(int rowCount, int columnCount) /// /// Enumerates all values of the matrix. /// + /// + /// for a version that returns stack-allocated value tuples to save transient heap allocations (saves performance overhead of allocations + garbage collection) of the class. + /// /// Enumeration of tuples (i, j, a[i, j]). public abstract IEnumerable> EnumerateIndexed(); + /// + /// Enumerates all values of the matrix, but returns as stack-allocated value tuples instead of heap-allocated tuples. + /// + /// Enumeration of tuples (i, j, a[i, j]). + public abstract IEnumerable<(int row, int column, T value)> EnumerateIndexedAsValueTuples(); + /// /// Enumerates all values of the matrix. /// diff --git a/CSparse/Storage/CompressedColumnStorage.cs b/CSparse/Storage/CompressedColumnStorage.cs index e6a1b70..2329119 100644 --- a/CSparse/Storage/CompressedColumnStorage.cs +++ b/CSparse/Storage/CompressedColumnStorage.cs @@ -110,7 +110,7 @@ public CompressedColumnStorage(int rowCount, int columnCount, T[] values, int[] /// public static CompressedColumnStorage OfMatrix(Matrix matrix) { - var c = Converter.FromEnumerable(matrix.EnumerateIndexed(), matrix.RowCount, matrix.ColumnCount); + var c = Converter.FromEnumerable(matrix.EnumerateIndexedAsValueTuples(), matrix.RowCount, matrix.ColumnCount); return Converter.ToCompressedColumnStorage(c); } @@ -146,6 +146,9 @@ public static CompressedColumnStorage OfIndexed(CoordinateStorage coordina /// /// Create a new sparse matrix as a copy of the given indexed enumerable. /// + /// The number of rows. + /// The number of columns. + /// Tuples with the three elements of row, column, and the value that belongs at that position. public static CompressedColumnStorage OfIndexed(int rows, int columns, IEnumerable> enumerable) { var c = Converter.FromEnumerable(enumerable, rows, columns); @@ -153,6 +156,19 @@ public static CompressedColumnStorage OfIndexed(int rows, int columns, IEnume return Converter.ToCompressedColumnStorage(c); } + /// + /// Create a new sparse matrix as a copy of the given indexed enumerable using a value tuple. + /// + /// The number of rows. + /// The number of columns. + /// Value tuples with the three elements of row, column, and the value that belongs at that position. + public static CompressedColumnStorage OfIndexed(int rows, int columns, IEnumerable<(int row, int column, T value)> enumerable) + { + var c = Converter.FromEnumerable(enumerable, rows, columns); + + return Converter.ToCompressedColumnStorage(c); + } + /// /// Create a new sparse matrix as a copy of the given array (row-major). /// @@ -564,6 +580,15 @@ public CompressedColumnStorage Clone(bool values = true) /// public override IEnumerable> EnumerateIndexed() + { + foreach (var valueTuple in EnumerateIndexedAsValueTuples()) + { + yield return Tuple.Create(valueTuple.row, valueTuple.column, valueTuple.value); + } + } + + /// + public override IEnumerable<(int row, int column, T value)> EnumerateIndexedAsValueTuples() { var ax = Values; var ap = ColumnPointers; @@ -574,7 +599,7 @@ public override IEnumerable> EnumerateIndexed() var end = ap[i + 1]; for (var j = ap[i]; j < end; j++) { - yield return new Tuple(ai[j], i, ax[j]); + yield return (ai[j], i, ax[j]); } } } diff --git a/CSparse/Storage/DenseColumnMajorStorage.cs b/CSparse/Storage/DenseColumnMajorStorage.cs index 053a6da..ae7c653 100644 --- a/CSparse/Storage/DenseColumnMajorStorage.cs +++ b/CSparse/Storage/DenseColumnMajorStorage.cs @@ -165,8 +165,8 @@ public static DenseColumnMajorStorage OfDiagonalArray(T[] diagonal) { int order = diagonal.Length; - var A = Create(order, order); - + var A = Create(order, order); + for (int i = 0; i < order; i++) { A.At(i, i, diagonal[i]); @@ -547,12 +547,21 @@ public override void Clear() /// public override IEnumerable> EnumerateIndexed() + { + foreach (var valueTuple in EnumerateIndexedAsValueTuples()) + { + yield return Tuple.Create(valueTuple.row, valueTuple.column, valueTuple.value); + } + } + + /// + public override IEnumerable<(int row, int column, T value)> EnumerateIndexedAsValueTuples() { for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { - yield return new Tuple(row, column, Values[(column * rows) + row]); + yield return (row, column, Values[(column * rows) + row]); } } }