/// <summary> /// Returns the indices of the diagonal entries in the sparse matrix storage. /// </summary> /// <param name="storage"></param> /// <param name="throwOnMissingDiag"></param> /// <returns>Indices of the diagonal entries.</returns> public static int[] FindDiagonalIndices <T>(this SparseCompressedRowMatrixStorage <T> storage, bool throwOnMissingDiag = false) where T : struct, IEquatable <T>, IFormattable { return(Helper.FindDiagonalIndices(storage.RowCount, storage.RowPointers, storage.ColumnIndices, throwOnMissingDiag)); }
public static SparseCompressedRowMatrixStorage <T> OfColumnArrays(T[][] data) { var storage = new SparseCompressedRowMatrixStorage <T>(data[0].Length, data.Length); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); for (int row = 0; row < storage.RowCount; row++) { rowPointers[row] = values.Count; for (int col = 0; col < storage.ColumnCount; col++) { T x = data[col][row]; if (!Zero.Equals(x)) { values.Add(x); columnIndices.Add(col); } } } rowPointers[storage.RowCount] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
/// <summary> /// Permutes the columns of a matrix in CSR format, B = A * P, where P represents /// a permutation matrix. /// </summary> /// <param name="storage">Input storage.</param> /// <param name="target">Target storage.</param> /// <param name="perm">Permutation array of length ColumnCount.</param> /// <param name="copy">Copy matrix values (not needed if used 'in place').</param> /// <param name="sorted">Ensure that column indices will be sorted.</param> /// <remarks> /// The permutation matrix P maps column j into column perm(j), i.e., /// on return a(i,j) in the original matrix becomes a(i,perm(j)) in the /// output matrix. /// /// Notes: /// /// 1. This routine is in place: aj, bj can be the same. /// 2. If the matrix is initially sorted (by increasing column number) /// then bx, bi, bj may not be on return. /// </remarks> public static void PermuteColumns <T>(this SparseCompressedRowMatrixStorage <T> storage, SparseCompressedRowMatrixStorage <T> target, int[] perm, bool copy = false, bool sorted = true) where T : struct, IEquatable <T>, IFormattable { int n = storage.RowCount; var ax = storage.Values; var ap = storage.RowPointers; var ai = storage.ColumnIndices; var bx = target.Values; var bp = target.RowPointers; var bi = target.ColumnIndices; int i, nnz = ap[n]; for (i = 0; i < nnz; i++) { bi[i] = perm[ai[i]]; } if (copy) { Array.Copy(ax, bx, nnz); Array.Copy(ap, bp, n); } if (sorted) { Helper.SortIndices(storage.RowCount, bx, bp, bi); } }
public static SparseCompressedRowMatrixStorage <T> OfArray(T[,] array) { var storage = new SparseCompressedRowMatrixStorage <T>(array.GetLength(0), array.GetLength(1)); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); for (int row = 0; row < storage.RowCount; row++) { rowPointers[row] = values.Count; for (int col = 0; col < storage.ColumnCount; col++) { if (!Zero.Equals(array[row, col])) { values.Add(array[row, col]); columnIndices.Add(col); } } } rowPointers[storage.RowCount] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
public static SparseCompressedRowMatrixStorage <T> OfRowMajorEnumerable(int rows, int columns, IEnumerable <T> data) { var storage = new SparseCompressedRowMatrixStorage <T>(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); using (var iterator = data.GetEnumerator()) { for (int row = 0; row < rows; row++) { rowPointers[row] = values.Count; for (int col = 0; col < columns; col++) { iterator.MoveNext(); if (!Zero.Equals(iterator.Current)) { values.Add(iterator.Current); columnIndices.Add(col); } } } } rowPointers[rows] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
/// <summary> /// Extract row from storage. /// </summary> /// <param name="storage"></param> /// <param name="rowIndex">The row index to extract.</param> /// <param name="target">Dense array.</param> /// <returns>The requested row.</returns> public static void GetRow <T>(this SparseCompressedRowMatrixStorage <T> storage, int rowIndex, T[] target, ExistingData existingData = ExistingData.Clear) where T : struct, IEquatable <T>, IFormattable { if (target.Length != storage.ColumnCount) { throw new Exception(); } if (existingData == ExistingData.Clear) { Array.Clear(target, 0, target.Length); } var ap = storage.RowPointers; var ai = storage.ColumnIndices; var ax = storage.Values; int rowEnd = ap[rowIndex + 1]; for (int k = ap[rowIndex]; k < rowEnd; k++) { target[ai[k]] = ax[k]; } }
public static SparseCompressedRowMatrixStorage <T> OfColumnMajorList(int rows, int columns, IList <T> data) { if (rows * columns != data.Count) { throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions); } var storage = new SparseCompressedRowMatrixStorage <T>(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); for (int row = 0; row < rows; row++) { rowPointers[row] = values.Count; for (int col = 0; col < columns; col++) { var item = data[row + (col * rows)]; if (!Zero.Equals(item)) { values.Add(item); columnIndices.Add(col); } } } rowPointers[rows] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
// INITIALIZATION public static SparseCompressedRowMatrixStorage <T> OfMatrix(MatrixStorage <T> matrix) { var storage = new SparseCompressedRowMatrixStorage <T>(matrix.RowCount, matrix.ColumnCount); matrix.CopyToUnchecked(storage, skipClearing: true); return(storage); }
public static SparseCompressedRowMatrixStorage <T> OfInit(int rows, int columns, Func <int, int, T> init) { var storage = new SparseCompressedRowMatrixStorage <T>(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); for (int row = 0; row < rows; row++) { rowPointers[row] = values.Count; for (int col = 0; col < columns; col++) { var x = init(row, col); if (!Zero.Equals(x)) { values.Add(x); columnIndices.Add(col); } } } rowPointers[rows] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
public static SparseCompressedRowMatrixStorage <T> OfColumnVectors(VectorStorage <T>[] data) { var storage = new SparseCompressedRowMatrixStorage <T>(data[0].Length, data.Length); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); // TODO PERF: Optimize for sparse and dense cases for (int row = 0; row < storage.RowCount; row++) { rowPointers[row] = values.Count; for (int col = 0; col < storage.ColumnCount; col++) { var x = data[col].At(row); if (!Zero.Equals(x)) { values.Add(x); columnIndices.Add(col); } } } rowPointers[storage.RowCount] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
public static SparseCompressedRowMatrixStorage <T> OfColumnEnumerables(int rows, int columns, IEnumerable <IEnumerable <T> > data) { var trows = new List <Tuple <int, T> > [rows]; using (var columnIterator = data.GetEnumerator()) { for (int column = 0; column < columns; column++) { if (!columnIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, columns)); } using (var rowIterator = columnIterator.Current.GetEnumerator()) { for (int row = 0; row < rows; row++) { if (!rowIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, rows)); } if (!Zero.Equals(rowIterator.Current)) { var trow = trows[row] ?? (trows[row] = new List <Tuple <int, T> >()); trow.Add(new Tuple <int, T>(column, rowIterator.Current)); } } } } } 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); }
void CopyToUnchecked(SparseCompressedRowMatrixStorage <T> target, ExistingData existingData) { if (existingData == ExistingData.Clear) { target.Clear(); } for (int i = 0; i < Data.Length; i++) { target.At(i, i, Data[i]); } }
void CopyToUnchecked(SparseCompressedRowMatrixStorage <T> target, bool skipClearing) { if (!skipClearing) { target.Clear(); } for (int i = 0; i < Data.Length; i++) { target.At(i, i, Data[i]); } }
void CopyToUnchecked(SparseCompressedRowMatrixStorage <T> target) { target.Values = new T[ValueCount]; target.ColumnIndices = new int[ValueCount]; if (ValueCount != 0) { Array.Copy(Values, target.Values, ValueCount); Buffer.BlockCopy(ColumnIndices, 0, target.ColumnIndices, 0, ValueCount * Constants.SizeOfInt); Buffer.BlockCopy(RowPointers, 0, target.RowPointers, 0, (RowCount + 1) * Constants.SizeOfInt); } }
public static SparseCompressedRowMatrixStorage <T> OfRowEnumerables <TRow>(int rows, int columns, IEnumerable <TRow> data) // NOTE: flexible typing to 'backport' generic covariance. where TRow : IEnumerable <T> { if (data == null) { throw new ArgumentNullException("data"); } var storage = new SparseCompressedRowMatrixStorage <T>(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); using (var rowIterator = data.GetEnumerator()) { for (int row = 0; row < rows; row++) { if (!rowIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, rows)); } rowPointers[row] = values.Count; using (var columnIterator = rowIterator.Current.GetEnumerator()) { for (int col = 0; col < columns; col++) { if (!columnIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, columns)); } if (!Zero.Equals(columnIterator.Current)) { values.Add(columnIterator.Current); columnIndices.Add(col); } } if (columnIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, columns)); } } } if (rowIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, rows)); } } storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); storage.ValueCount = values.Count; return(storage); }
public static SparseCompressedRowMatrixStorage <T> OfRowEnumerables(int rows, int columns, IEnumerable <IEnumerable <T> > data) { var storage = new SparseCompressedRowMatrixStorage <T>(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); using (var rowIterator = data.GetEnumerator()) { for (int row = 0; row < rows; row++) { if (!rowIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, rows)); } rowPointers[row] = values.Count; using (var columnIterator = rowIterator.Current.GetEnumerator()) { for (int col = 0; col < columns; col++) { if (!columnIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, columns)); } if (!Zero.Equals(columnIterator.Current)) { values.Add(columnIterator.Current); columnIndices.Add(col); } } if (columnIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, columns)); } } } if (rowIterator.MoveNext()) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, rows)); } } rowPointers[rows] = values.Count; storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); return(storage); }
void CopySubMatrixTo(SparseCompressedRowMatrixStorage <T> target, int sourceRowIndex, int targetRowIndex, int rowCount, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing) { if (target == null) { throw new ArgumentNullException("target"); } ValidateSubMatrixRange(target, sourceRowIndex, targetRowIndex, rowCount, sourceColumnIndex, targetColumnIndex, columnCount); if (!skipClearing) { target.Clear(targetRowIndex, rowCount, targetColumnIndex, columnCount); } if (sourceRowIndex == sourceColumnIndex) { for (var i = 0; i < Math.Min(columnCount, rowCount); i++) { target.At(i + targetRowIndex, i + targetColumnIndex, Data[sourceRowIndex + i]); } } else if (sourceRowIndex > sourceColumnIndex && sourceColumnIndex + columnCount > sourceRowIndex) { // column by column, but skip resulting zero columns at the beginning int columnInit = sourceRowIndex - sourceColumnIndex; for (var i = 0; i < Math.Min(columnCount - columnInit, rowCount); i++) { target.At(i + targetRowIndex, columnInit + i + targetColumnIndex, Data[sourceRowIndex + i]); } } else if (sourceRowIndex < sourceColumnIndex && sourceRowIndex + rowCount > sourceColumnIndex) { // row by row, but skip resulting zero rows at the beginning int rowInit = sourceColumnIndex - sourceRowIndex; for (var i = 0; i < Math.Min(columnCount, rowCount - rowInit); i++) { target.At(rowInit + i + targetRowIndex, i + targetColumnIndex, Data[sourceColumnIndex + i]); } } // else: all zero, nop }
public static SparseCompressedRowMatrixStorage <T> OfIndexedEnumerable(int rows, int columns, IEnumerable <Tuple <int, int, T> > data) { if (data == null) { throw new ArgumentNullException("data"); } var trows = new List <Tuple <int, T> > [rows]; foreach (var item in data) { if (!Zero.Equals(item.Item3)) { var row = trows[item.Item1] ?? (trows[item.Item1] = new List <Tuple <int, T> >()); row.Add(new Tuple <int, T>(item.Item2, item.Item3)); } } 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++; } } } storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); storage.ValueCount = values.Count; return(storage); }
/// <summary> /// Permute the rows of a matrix in CSR format, B = P * A, where P represents /// a permutation matrix. /// </summary> /// <param name="storage">Input storage.</param> /// <param name="target">Target storage.</param> /// <param name="perm">Permutation array of length RowCount.</param> /// <param name="sorted">Ensure that column indices will be sorted.</param> /// <remarks> /// The permutation P is defined through the array perm: for each j, /// perm(j) represents the destination row number of row number j: /// /// a(i,j) in the original matrix becomes a(perm(i),j) in the output matrix. /// </remarks> public static void PermuteRows <T>(this SparseCompressedRowMatrixStorage <T> storage, SparseCompressedRowMatrixStorage <T> target, int[] perm, bool sorted = true) where T : struct, IEquatable <T>, IFormattable { int k, n = storage.RowCount; var ax = storage.Values; var ap = storage.RowPointers; var ai = storage.ColumnIndices; var bx = target.Values; var bp = target.RowPointers; var bi = target.ColumnIndices; // Determine pointers for output matix. for (int i = 0; i < n; i++) { k = perm[i]; bp[k + 1] = ap[i + 1] - ap[i]; } // Get pointers from lengths bp[0] = 0; for (int i = 0; i < n; i++) { bp[i + 1] += bp[i]; } // Copying for (int i = 0; i < n; i++) { // Old row = i, new row = perm(i), k = new pointer k = bp[perm[i]]; for (int j = ap[i]; j < ap[i + 1]; j++) { bi[k] = ai[j]; bx[k] = ax[j]; k = k + 1; } } if (sorted) { Helper.SortIndices(storage.RowCount, bx, bp, bi); } }
/// <summary> /// Drops entries from a sparse matrix. /// </summary> /// <param name="storage">The sparse storage.</param> /// <param name="func">Drop element a_{i,j} if func(i, j, aij) is false.</param> /// <param name="sorted">Ensure that column indices will be sorted.</param> /// <returns>New number of entries in A.</returns> public static int Keep <T>(this SparseCompressedRowMatrixStorage <T> storage, Func <int, int, T, bool> func, bool sorted = true) where T : struct, IEquatable <T>, IFormattable { int rowCount = storage.RowCount; var ax = storage.Values; var ap = storage.RowPointers; var ai = storage.ColumnIndices; int i, j, nz = 0; for (i = 0; i < rowCount; i++) { j = ap[i]; // Record new location of row i. ap[i] = nz; for (; j < ap[i + 1]; j++) { if (func(i, ai[j], ax[j])) { // Keep A(i,j). ax[nz] = ax[j]; ai[nz] = ai[j]; nz++; } } } // Record new nonzero count. ap[rowCount] = nz; if (sorted) { Helper.SortIndices(storage.RowCount, ax, ap, ai); } // Remove extra space. Array.Resize(ref storage.Values, nz); Array.Resize(ref storage.ColumnIndices, nz); return(nz); }
void CopyTo(SparseCompressedRowMatrixStorage <T> target, bool skipClearing) { if (target == null) { throw new ArgumentNullException("target"); } 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 (!skipClearing) { target.Clear(); } for (int i = 0; i < Data.Length; i++) { target.At(i, i, Data[i]); } }
public static SparseCompressedRowMatrixStorage <T> OfDiagonalInit(int rows, int columns, Func <int, T> init) { var storage = new SparseCompressedRowMatrixStorage <T>(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List <int>(); var values = new List <T>(); for (int i = 0; i < Math.Min(rows, columns); i++) { rowPointers[i] = values.Count; var x = init(i); if (!Zero.Equals(x)) { values.Add(x); columnIndices.Add(i); } } storage.ColumnIndices = columnIndices.ToArray(); storage.Values = values.ToArray(); storage.ValueCount = values.Count; return(storage); }
void TransposeToUnchecked(SparseCompressedRowMatrixStorage<T> target) { var rowPointers = target.RowPointers; var columnIndices = new List<int>(); var values = new List<T>(); for (int j = 0; j < ColumnCount; j++) { rowPointers[j] = values.Count; var index = j * RowCount; for (int i = 0; i < RowCount; i++) { if (!Zero.Equals(Data[index + i])) { values.Add(Data[index + i]); columnIndices.Add(i); } } } rowPointers[ColumnCount] = values.Count; target.ColumnIndices = columnIndices.ToArray(); target.Values = values.ToArray(); }
void CopyTo(SparseCompressedRowMatrixStorage <T> target) { if (ReferenceEquals(this, target)) { return; } 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"); } target.ValueCount = ValueCount; target.Values = new T[ValueCount]; target.ColumnIndices = new int[ValueCount]; if (ValueCount != 0) { Array.Copy(Values, target.Values, ValueCount); Buffer.BlockCopy(ColumnIndices, 0, target.ColumnIndices, 0, ValueCount * Constants.SizeOfInt); Buffer.BlockCopy(RowPointers, 0, target.RowPointers, 0, RowCount * Constants.SizeOfInt); } }
/// <summary> /// Extract rows from given storage. /// </summary> /// <param name="storage"></param> /// <param name="rowIndices">The rows to extract.</param> /// <param name="target">The target storage (will be resized, if needed).</param> /// <returns>The requested sub-matrix.</returns> public static void GetRows <T>(this SparseCompressedRowMatrixStorage <T> storage, int[] rowIndices, SparseCompressedRowMatrixStorage <T> target) where T : struct, IEquatable <T>, IFormattable { var ap = storage.RowPointers; var ai = storage.ColumnIndices; var ax = storage.Values; int count = rowIndices.Length; if (target.RowCount != count || storage.ColumnCount != target.ColumnCount) { throw new Exception(); } int i, needed = 0; // Compute space needed. for (int k = 0; k < count; k++) { i = rowIndices[k]; needed += ap[i + 1] - ap[i]; } var cp = target.RowPointers; var ci = target.ColumnIndices; var cx = target.Values; // We assume that cx and ci have the same length. int nz = cx.Length; if (nz < needed) { // Resize workspace. Array.Resize(ref ci, needed); Array.Resize(ref cx, needed); } nz = 0; for (int k = 0; k < count; k++) { i = rowIndices[k]; int rowEnd = ap[i + 1]; cp[k] = nz; // Copy row. for (int j = ap[i]; j < rowEnd; j++) { cx[nz] = ax[j]; ci[nz] = ai[j]; nz = nz + 1; } } cp[count] = nz; target.ColumnIndices = ci; target.Values = cx; }
void CopySubMatrixToUnchecked(SparseCompressedRowMatrixStorage <T> target, int sourceRowIndex, int targetRowIndex, int rowCount, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing) { var rowOffset = targetRowIndex - sourceRowIndex; var columnOffset = targetColumnIndex - sourceColumnIndex; // special case for empty target - much faster if (target.ValueCount == 0) { // note: ValueCount is maximum resulting ValueCount (just using max to avoid internal copying) // resulting arrays will likely be smaller - unless all values fit in the chosen range. var values = new List <T>(ValueCount); var columnIndices = new List <int>(ValueCount); var rowPointers = target.RowPointers; for (int i = sourceRowIndex, row = 0; i < sourceRowIndex + rowCount; i++, row++) { rowPointers[i + rowOffset] = values.Count; var startIndex = RowPointers[i]; var endIndex = RowPointers[i + 1]; // note: we might be able to replace this loop with Array.Copy (perf) for (int j = startIndex; j < endIndex; j++) { // check if the column index is in the range if ((ColumnIndices[j] >= sourceColumnIndex) && (ColumnIndices[j] < sourceColumnIndex + columnCount)) { values.Add(Values[j]); columnIndices.Add(ColumnIndices[j] + columnOffset); } } } for (int i = targetRowIndex + rowCount; i < rowPointers.Length; i++) { rowPointers[i] = values.Count; } target.RowPointers[target.RowCount] = values.Count; target.Values = values.ToArray(); target.ColumnIndices = columnIndices.ToArray(); return; } if (!skipClearing) { target.Clear(targetRowIndex, rowCount, targetColumnIndex, columnCount); } // NOTE: potential for more efficient implementation for (int i = sourceRowIndex, row = 0; i < sourceRowIndex + rowCount; i++, row++) { var startIndex = RowPointers[i]; var endIndex = RowPointers[i + 1]; for (int j = startIndex; j < endIndex; j++) { // check if the column index is in the range if ((ColumnIndices[j] >= sourceColumnIndex) && (ColumnIndices[j] < sourceColumnIndex + columnCount)) { var column = ColumnIndices[j] - sourceColumnIndex; target.At(targetRowIndex + row, targetColumnIndex + column, Values[j]); } } } }
/// <summary> /// Replaces the rows of the storage with the given rows. /// </summary> /// <param name="storage"></param> /// <param name="rowIndices">The indices of the rows to replace.</param> /// <param name="source">The storage containing the rows to copy.</param> public static void SetRows <T>(this SparseCompressedRowMatrixStorage <T> storage, int[] rowIndices, SparseCompressedRowMatrixStorage <T> source) where T : struct, IEquatable <T>, IFormattable { var ap = storage.RowPointers; var ai = storage.ColumnIndices; var ax = storage.Values; int i, n = ap.Length; int rowCount = rowIndices.Length; int valueCount = 0; // Count the number of nonzeros in given rows of input matrix. for (int k = 0; k < rowCount; k++) { i = rowIndices[k]; valueCount += ap[i + 1] - ap[i]; } int nz = storage.ValueCount; int size = nz + (source.ValueCount - valueCount); // Check if the matrix storage has to be resized. if (ai.Length < size) { Array.Resize(ref ai, size); Array.Resize(ref ax, size); storage.ColumnIndices = ai; storage.Values = ax; } size = ai.Length; var cp = source.RowPointers; var ci = source.ColumnIndices; var cx = source.Values; int count, length, rowStart, rowEnd; // Replace the rows. for (int k = 0; k < rowCount; k++) { i = rowIndices[k]; rowStart = ap[i]; rowEnd = ap[i + 1]; // Length of the row to insert. length = cp[k + 1] - cp[k]; // Number of elements to shift. count = nz - rowEnd; // Copy all data behind the current block. Array.Copy(ai, rowEnd, ai, rowStart + length, count); Array.Copy(ax, rowEnd, ax, rowStart + length, count); // Replace row. Array.Copy(ci, cp[k], ai, rowStart, length); Array.Copy(cx, cp[k], ax, rowStart, length); // The difference of the row lengths. count = length - (rowEnd - rowStart); // Fix row pointers. for (int j = i + 1; j < n; j++) { ap[j] += count; } nz += count; } }
/// <summary> /// Extract columns from given storage. /// </summary> /// <param name="storage"></param> /// <param name="columnIndices">The columns to extract.</param> /// <param name="target">The target storage (will be resized, if needed).</param> /// <returns>The requested sub-matrix.</returns> public static void GetColumns <T>(this SparseCompressedRowMatrixStorage <T> storage, int[] columnIndices, SparseCompressedRowMatrixStorage <T> target) where T : struct, IEquatable <T>, IFormattable { var ap = storage.RowPointers; var ai = storage.ColumnIndices; var ax = storage.Values; int count = columnIndices.Length; int rowCount = storage.RowCount; if (target.ColumnCount != count || rowCount != target.RowCount) { throw new Exception(); } int i, j, nz, needed = 0; var columnCounts = new int[storage.ColumnCount]; nz = storage.ValueCount; // Count columns. for (i = 0; i < nz; i++) { columnCounts[ai[i]]++; } // Compute space needed. for (int k = 0; k < count; k++) { needed += columnCounts[columnIndices[k]]; } var cp = target.RowPointers; var ci = target.ColumnIndices; var cx = target.Values; // We assume that cx and ci have the same length. nz = cx.Length; if (nz < needed) { // Resize workspace. Array.Resize(ref ci, needed); Array.Resize(ref cx, needed); } int column, rowStart, rowEnd; nz = 0; for (int k = 0; k < rowCount; k++) { rowStart = ap[k]; rowEnd = ap[k + 1]; cp[k] = nz; // Look for columns in current row. for (j = 0; j < count; j++) { column = columnIndices[j]; i = Array.BinarySearch(ai, rowStart, rowEnd - rowStart, column); if (i >= 0) { ci[nz] = j; cx[nz] = ax[i]; nz = nz + 1; } } } cp[rowCount] = nz; target.ColumnIndices = ci; target.Values = cx; }