|
|
|
@ -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 }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -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.
|
|
|
|
/// </summary>
|
|
|
|
public Matrix<T> 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) |
|
|
|
/// <param name="rows">The number of rows.</param>
|
|
|
|
/// <param name="columns">The number of columns.</param>
|
|
|
|
/// <param name="valueCount">The number of stored values including explicit zeros.</param>
|
|
|
|
/// <param name="rowIndices">The row index array of the coordinate format.</param>
|
|
|
|
/// <param name="columnIndices">The column index array of the coordinate format.</param>
|
|
|
|
/// <param name="values">The data array of the coordinate format.</param>
|
|
|
|
/// <returns>The sparse matrix from the coordinate format.</returns>
|
|
|
|
/// <remarks>Duplicate entries will be summed together and
|
|
|
|
/// explicit zeros will be not intentionally removed.</remarks>
|
|
|
|
public Matrix<T> 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.
|
|
|
|
/// </summary>
|
|
|
|
public Matrix<T> 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) |
|
|
|
/// <param name="rows">The number of rows.</param>
|
|
|
|
/// <param name="columns">The number of columns.</param>
|
|
|
|
/// <param name="valueCount">The number of stored values including explicit zeros.</param>
|
|
|
|
/// <param name="rowPointers">The row pointer array of the compressed sparse row format.</param>
|
|
|
|
/// <param name="columnIndices">The column index array of the compressed sparse row format.</param>
|
|
|
|
/// <param name="values">The data array of the compressed sparse row format.</param>
|
|
|
|
/// <returns>The sparse matrix from the compressed sparse row format.</returns>
|
|
|
|
/// <remarks>Duplicate entries will be summed together and
|
|
|
|
/// explicit zeros will be not intentionally removed.</remarks>
|
|
|
|
public Matrix<T> 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<T>(rows, columns, rowPointers, columnIndices, values); |
|
|
|
var storage = new SparseCompressedRowMatrixStorage<T>(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.
|
|
|
|
/// </summary>
|
|
|
|
public Matrix<T> 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) |
|
|
|
/// <param name="rows">The number of rows.</param>
|
|
|
|
/// <param name="columns">The number of columns.</param>
|
|
|
|
/// <param name="valueCount">The number of stored values including explicit zeros.</param>
|
|
|
|
/// <param name="rowIndices">The row index array of the compressed sparse column format.</param>
|
|
|
|
/// <param name="columnPointers">The column pointer array of the compressed sparse column format.</param>
|
|
|
|
/// <param name="values">The data array of the compressed sparse column format.</param>
|
|
|
|
/// <returns>The sparse matrix from the compressed sparse column format.</returns>
|
|
|
|
/// <remarks>Duplicate entries will be summed together and
|
|
|
|
/// explicit zeros will be not intentionally removed.</remarks>
|
|
|
|
public Matrix<T> 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<T> 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); |
|
|
|
|