diff --git a/src/Numerics/LinearAlgebra/Builder.cs b/src/Numerics/LinearAlgebra/Builder.cs
index 4b550830..0a43c00b 100644
--- a/src/Numerics/LinearAlgebra/Builder.cs
+++ b/src/Numerics/LinearAlgebra/Builder.cs
@@ -1166,6 +1166,7 @@ namespace MathNet.Numerics.LinearAlgebra
return m;
}
+
// Representation of Sparse Matrix
//
// Matrix A = [ 0 b 0 h 0 0 ]
@@ -1173,22 +1174,22 @@ namespace MathNet.Numerics.LinearAlgebra
// [ 0 0 f j l n ]
// [ 0 d g k m 0 ]
//
- // Rows = 4, Columns = 6, NonZeroCount = 14
+ // rows = 4, columns = 6, valueCount = 14
//
- // (1) COO, Coordinate Format:
+ // (1) COO, Coordinate, ijv, or triplet format:
// cooRowIndices = { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 }
// cooColumnIndices = { 1, 3, 0, 1, 2, 3, 2, 3, 4, 5, 1, 2, 3, 4 }
// cooValues = { b, h, a, c, e, i, f, j, l, n, d, g, k, m }
//
- // (2) CSR, Compressed Sparse Row representation:
+ // (2) CSR, Compressed Sparse Row or Compressed Row Storage(CRS) or Yale format:
// csrRowPointers = { 0, 2, 6, 10, 14 }
// csrColumnIndices = { 1, 3, 0, 1, 2, 3, 2, 3, 4, 5, 1, 2, 3, 4 }
// csrValues = { b, h, a, c, e, i, f, j, l, n, d, g, k, m }
//
- // (3) CSC, Compressed Sparse Column representation:
- // csrColumnPointers = { 0, 1, 4, 7, 11, 13, 14 }
- // csrRowIndices = { 1, 0, 1, 3, 1, 2, 3, 0, 1, 2, 3, 2, 3, 2 }
- // csrValues = { a, b, c, d, e, f, g, h, i, j, k, l, m, n }
+ // (3) CSC, Compressed Sparse Column or Compressed Column Storage(CCS) format:
+ // cscColumnPointers = { 0, 1, 4, 7, 11, 13, 14 }
+ // cscRowIndices = { 1, 0, 1, 3, 1, 2, 3, 0, 1, 2, 3, 2, 3, 2 }
+ // cscValues = { a, b, c, d, e, f, g, h, i, j, k, l, m, n }
///
@@ -1196,29 +1197,38 @@ namespace MathNet.Numerics.LinearAlgebra
/// This new matrix will be independent from the given arrays.
/// A new memory block will be allocated for storing the matrix.
///
- public Matrix SparseFromCoordinateFormat(int rows, int columns, int nonZeroCount, int[] cooRowIndices, int[] cooColumnIndices, T[] cooValues)
- {
- if (cooValues == null)
- throw new NullReferenceException(nameof(cooValues));
- if (cooRowIndices == null)
- throw new NullReferenceException(nameof(cooRowIndices));
- if (cooColumnIndices == null)
- throw new NullReferenceException(nameof(cooColumnIndices));
-
- if (cooRowIndices.Length < nonZeroCount || cooColumnIndices.Length < nonZeroCount || cooValues.Length < nonZeroCount)
+ /// The number of rows.
+ /// The number of columns.
+ /// The number of stored values including explicit zeros.
+ /// The row index array of the coordinate format.
+ /// The column index array of the coordinate format.
+ /// The data array of the coordinate format.
+ /// The sparse matrix from the coordinate format.
+ /// Duplicate entries will be summed together and
+ /// explicit zeros will be not intentionally removed.
+ public Matrix SparseFromCoordinateFormat(int rows, int columns, int valueCount, int[] rowIndices, int[] columnIndices, T[] values)
+ {
+ if (values == null)
+ throw new NullReferenceException(nameof(values));
+ if (rowIndices == null)
+ throw new NullReferenceException(nameof(rowIndices));
+ if (columnIndices == null)
+ throw new NullReferenceException(nameof(columnIndices));
+
+ if (rowIndices.Length < valueCount || columnIndices.Length < valueCount || values.Length < valueCount)
{
- throw new Exception($"The given array has the wrong length. Should be {nonZeroCount}.");
+ throw new Exception($"The given array has the wrong length. Should be {valueCount}.");
}
// convert from COO to CSR
- var csrValues = new T[nonZeroCount];
- var csrColumnIndices = new int[nonZeroCount];
+ var csrValues = new T[valueCount];
+ var csrColumnIndices = new int[valueCount];
var csrRowPointers = new int[rows + 1];
- for (int i = 0; i < nonZeroCount; i++)
+ for (int i = 0; i < valueCount; i++)
{
- csrRowPointers[cooRowIndices[i]]++;
+ csrRowPointers[rowIndices[i]]++;
}
for (int i = 0, cumsum = 0; i < rows; i++)
{
@@ -1226,15 +1236,15 @@ namespace MathNet.Numerics.LinearAlgebra
csrRowPointers[i] = cumsum;
cumsum += temp;
}
- csrRowPointers[rows] = nonZeroCount;
+ csrRowPointers[rows] = valueCount;
- for (int i = 0; i < nonZeroCount; i++)
+ for (int i = 0; i < valueCount; i++)
{
- var row = cooRowIndices[i];
+ var row = rowIndices[i];
var loc = csrRowPointers[row];
- csrColumnIndices[loc] = cooColumnIndices[i];
- csrValues[loc] = cooValues[i];
+ csrColumnIndices[loc] = columnIndices[i];
+ csrValues[loc] = values[i];
csrRowPointers[row]++;
}
@@ -1254,31 +1264,42 @@ namespace MathNet.Numerics.LinearAlgebra
/// This new matrix will be independent from the given arrays.
/// A new memory block will be allocated for storing the matrix.
///
- public Matrix SparseFromCompressedSparseRowFormat(int rows, int columns, int nonZeroCount, int[] csrRowPointers, int[] csrColumnIndices, T[] csrValues)
- {
- if (csrValues == null)
- throw new NullReferenceException(nameof(csrValues));
- if (csrColumnIndices == null)
- throw new NullReferenceException(nameof(csrColumnIndices));
- if (csrRowPointers == null)
- throw new NullReferenceException(nameof(csrRowPointers));
- if (csrRowPointers.Length < rows)
+ /// The number of rows.
+ /// The number of columns.
+ /// The number of stored values including explicit zeros.
+ /// The row pointer array of the compressed sparse row format.
+ /// The column index array of the compressed sparse row format.
+ /// The data array of the compressed sparse row format.
+ /// The sparse matrix from the compressed sparse row format.
+ /// Duplicate entries will be summed together and
+ /// explicit zeros will be not intentionally removed.
+ public Matrix SparseFromCompressedSparseRowFormat(int rows, int columns, int valueCount, int[] rowPointers, int[] columnIndices, T[] values)
+ {
+ if (values == null)
+ throw new NullReferenceException(nameof(values));
+ if (columnIndices == null)
+ throw new NullReferenceException(nameof(columnIndices));
+ if (rowPointers == null)
+ throw new NullReferenceException(nameof(rowPointers));
+ if (rowPointers.Length < rows)
{
throw new Exception($"The given array has the wrong length. Should be {rows + 1}.");
}
- if (nonZeroCount != csrRowPointers[rows])
+ if (valueCount != rowPointers[rows])
{
- throw new Exception($"{nameof(nonZeroCount)} should be same to {csrRowPointers[rows]}");
+ throw new Exception($"{nameof(valueCount)} should be same to {rowPointers[rows]}");
}
- var values = new T[nonZeroCount];
- Array.Copy(csrValues, values, nonZeroCount);
- var columnIndices = new int[nonZeroCount];
- Array.Copy(csrColumnIndices, columnIndices, nonZeroCount);
- var rowPointers = new int[rows + 1];
- Array.Copy(csrRowPointers, rowPointers, rows + 1);
+ // copy arrays to new memory block.
+
+ var csrValues = new T[valueCount];
+ Array.Copy(values, csrValues, valueCount);
+ var csrColumnIndices = new int[valueCount];
+ Array.Copy(columnIndices, csrColumnIndices, valueCount);
+ var csrRowPointers = new int[rows + 1];
+ Array.Copy(rowPointers, csrRowPointers, rows + 1);
- var storage = new SparseCompressedRowMatrixStorage(rows, columns, rowPointers, columnIndices, values);
+ var storage = new SparseCompressedRowMatrixStorage(rows, columns, csrRowPointers, csrColumnIndices, csrValues);
return Sparse(storage, true);
}
@@ -1287,34 +1308,43 @@ namespace MathNet.Numerics.LinearAlgebra
/// This new matrix will be independent from the given arrays.
/// A new memory block will be allocated for storing the matrix.
///
- public Matrix SparseFromCompressedSparseColumnFormat(int rows, int columns, int nonZeroCount, int[] cscRowIndices, int[] cscColumnPointers, T[] cscValues)
- {
- if (cscValues == null)
- throw new NullReferenceException(nameof(cscValues));
- if (cscRowIndices == null)
- throw new NullReferenceException(nameof(cscRowIndices));
- if (cscColumnPointers == null)
- throw new NullReferenceException(nameof(cscColumnPointers));
- if (cscColumnPointers.Length < columns)
+ /// The number of rows.
+ /// The number of columns.
+ /// The number of stored values including explicit zeros.
+ /// The row index array of the compressed sparse column format.
+ /// The column pointer array of the compressed sparse column format.
+ /// The data array of the compressed sparse column format.
+ /// The sparse matrix from the compressed sparse column format.
+ /// Duplicate entries will be summed together and
+ /// explicit zeros will be not intentionally removed.
+ public Matrix SparseFromCompressedSparseColumnFormat(int rows, int columns, int valueCount, int[] rowIndices, int[] columnPointers, T[] values)
+ {
+ if (values == null)
+ throw new NullReferenceException(nameof(values));
+ if (rowIndices == null)
+ throw new NullReferenceException(nameof(rowIndices));
+ if (columnPointers == null)
+ throw new NullReferenceException(nameof(columnPointers));
+ if (columnPointers.Length < columns)
{
throw new Exception($"The given array has the wrong length. Should be {columns + 1}.");
}
- if (nonZeroCount != cscColumnPointers[columns])
+ if (valueCount != columnPointers[columns])
{
- throw new Exception($"{nameof(nonZeroCount)} should be same to {cscColumnPointers[columns]}");
+ throw new Exception($"{nameof(valueCount)} should be same to {columnPointers[columns]}");
}
// convert from CSC to CSR
- var csrValues = new T[nonZeroCount];
+ var csrValues = new T[valueCount];
var csrRowPointers = new int[rows + 1];
- var csrColumnIndices = new int[nonZeroCount];
+ var csrColumnIndices = new int[valueCount];
for (int i = 0; i < columns; i++)
{
- for (int j = cscColumnPointers[i]; j < cscColumnPointers[i + 1]; j++)
+ for (int j = columnPointers[i]; j < columnPointers[i + 1]; j++)
{
- csrRowPointers[cscRowIndices[j] + 1]++;
+ csrRowPointers[rowIndices[j] + 1]++;
}
}
for (int i = 1; i < rows + 1; i++)
@@ -1324,12 +1354,12 @@ namespace MathNet.Numerics.LinearAlgebra
var curr = new int[rows];
for (int i = 0; i < columns; i++)
{
- for (int j = cscColumnPointers[i]; j < cscColumnPointers[i + 1]; j++)
+ for (int j = columnPointers[i]; j < columnPointers[i + 1]; j++)
{
- var loc = csrRowPointers[cscRowIndices[j]] + curr[cscRowIndices[j]];
- curr[cscRowIndices[j]]++;
+ var loc = csrRowPointers[rowIndices[j]] + curr[rowIndices[j]];
+ curr[rowIndices[j]]++;
csrColumnIndices[loc] = i;
- csrValues[loc] = cscValues[j];
+ csrValues[loc] = values[j];
}
}
@@ -1337,9 +1367,10 @@ namespace MathNet.Numerics.LinearAlgebra
return Sparse(storage, true);
}
+ // Eliminate duplicate entries by adding them together.
internal void SumDuplicates(SparseCompressedRowMatrixStorage storage)
{
- int nnz = 0;
+ int valueCount = 0;
for (int i = 0; i < storage.RowCount; i++)
{
int index = storage.RowPointers[i];
@@ -1361,16 +1392,16 @@ namespace MathNet.Numerics.LinearAlgebra
break;
}
}
- storage.ColumnIndices[nnz] = col;
- storage.Values[nnz] = val;
- nnz++;
+ storage.ColumnIndices[valueCount] = col;
+ storage.Values[valueCount] = val;
+ valueCount++;
}
- storage.RowPointers[i + 1] = nnz;
+ storage.RowPointers[i + 1] = valueCount;
}
// Remove extra space from arrays.
- Array.Resize(ref storage.Values, nnz);
- Array.Resize(ref storage.ColumnIndices, nnz);
+ Array.Resize(ref storage.Values, valueCount);
+ Array.Resize(ref storage.ColumnIndices, valueCount);
}
internal abstract T AddEntries(T x, T y);
diff --git a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
index 7cd7ec57..41fe9fe8 100644
--- a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
+++ b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
@@ -85,8 +85,9 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
ColumnIndices = columnIndices;
Values = values;
- // columnIndices may be not ordered.
- Normalize();
+ // Explicit zeros are not intentionally removed.
+ // Sort ColumnIndices.
+ NormalizeOrdering();
}
///