void SparseMatrix<T>::SubMatrixCols(SparseMatrix<T>& result, const std::vector<unsigned int>& col_indices) const { // extract entire columns from the source matrix to form the dest matrix unsigned int new_width = col_indices.size(); if (0u == new_width) throw std::logic_error("SparseMatrix: empty column set"); // check the column indices for validty and count nonzeros unsigned int new_size = 0; for (auto it=col_indices.begin(); it != col_indices.end(); ++it) { // index of next source column unsigned int c = *it; if (c >= width_) throw std::logic_error("SparseMatrix::SubMatrix: column index out of range"); // number of nonzeros in source column c new_size += (col_offsets_[c+1] - col_offsets_[c]); } if (0u == new_size) throw std::logic_error("SparseMatrix::SubMatrix: submatrix is the zero matrix"); // allocate memory in the result; won't allocate if sufficient memory available result.Reserve(height_, new_width, new_size); unsigned int* cols_b = result.ColBuffer(); unsigned int* rows_b = result.RowBuffer(); T* data_b = result.DataBuffer(); unsigned int c_dest = 0; unsigned int elt_count = 0; for (auto it=col_indices.begin(); it != col_indices.end(); ++it) { // index of the next source column unsigned int c = *it; // set element offset for the next dest column cols_b[c_dest] = elt_count; unsigned int start = col_offsets_[c]; unsigned int end = col_offsets_[c+1]; for (unsigned int offset = start; offset != end; ++offset) { rows_b[elt_count] = row_indices_[offset]; data_b[elt_count] = data_[offset]; ++elt_count; } // have now completed another column ++c_dest; } cols_b[new_width] = elt_count; assert(new_width == c_dest); // set the size of the new matrix explicitly, since Load() has been bypassed result.SetSize(elt_count); }
void SparseMatrix<T>::SubMatrixColsCompact(SparseMatrix<T>& result, const std::vector<unsigned int>& col_indices, std::vector<unsigned int>& old_to_new_rows, std::vector<unsigned int>& new_to_old_rows) const { const unsigned int UNUSED_ROW = 0xFFFFFFFF; // extract entire columns from the source matrix to form the dest matrix unsigned int new_width = col_indices.size(); if (0u == new_width) throw std::logic_error("SparseMatrix::SubMatrixColsCompact: empty column set"); // need one entry per original row in the row_map if (old_to_new_rows.size() < height_) old_to_new_rows.resize(height_); std::fill(old_to_new_rows.begin(), old_to_new_rows.begin() + height_, UNUSED_ROW); // no need to fill 'new_to_old_rows' // check the column indices for validty and count nonzeros unsigned int new_size = 0; for (auto it=col_indices.begin(); it != col_indices.end(); ++it) { // index of next source column unsigned int c = *it; if (c >= width_) throw std::logic_error("SparseMatrix::SubMatrixColsCompact: column index out of range"); // number of nonzeros in source column c new_size += (col_offsets_[c+1] - col_offsets_[c]); } if (0u == new_size) throw std::logic_error("SparseMatrix::SubMatrixColsCompact: submatrix is the zero matrix"); // allocate memory in the result; won't allocate if sufficient memory available result.Reserve(height_, new_width, new_size); unsigned int* cols_b = result.ColBuffer(); unsigned int* rows_b = result.RowBuffer(); T* data_b = result.DataBuffer(); unsigned int c_dest = 0; unsigned int elt_count = 0; for (auto it=col_indices.begin(); it != col_indices.end(); ++it) { // index of the next source column unsigned int c = *it; // set element offset for the next dest column cols_b[c_dest] = elt_count; unsigned int start = col_offsets_[c]; unsigned int end = col_offsets_[c+1]; for (unsigned int offset = start; offset != end; ++offset) { unsigned int row = row_indices_[offset]; old_to_new_rows[row] = row; rows_b[elt_count] = row; data_b[elt_count] = data_[offset]; ++elt_count; } // have now completed another column ++c_dest; } cols_b[new_width] = elt_count; assert(new_width == c_dest); // set the size of the new matrix explicitly, since Load() has been bypassed result.SetSize(elt_count); // determine the new height of the submatrix unsigned int new_height = 0; for (unsigned int r=0; r != height_; ++r) { if (UNUSED_ROW != old_to_new_rows[r]) ++new_height; } new_to_old_rows.resize(new_height); // renumber the rows in the submatrix unsigned int new_r = 0; for (unsigned int r=0; r<height_; ++r) { if (UNUSED_ROW != old_to_new_rows[r]) { old_to_new_rows[r] = new_r; new_to_old_rows[new_r] = r; ++new_r; } } // set the height of the new matrix explicitly assert(new_r == new_height); result.SetHeight(new_height); // re-index the rows in the submatrix for (unsigned int s=0; s != elt_count; ++s) { unsigned int old_row_index = rows_b[s]; rows_b[s] = old_to_new_rows[old_row_index]; } assert(result.Height() == new_height); assert(new_to_old_rows.size() == new_height); assert(old_to_new_rows.size() == height_); }
void SparseMatrix<T>::SubMatrix(SparseMatrix<T>& result, const unsigned int r0, const unsigned int c0, const unsigned int new_height, const unsigned int new_width) const { // one past the end of each range unsigned int r1 = r0 + new_height; unsigned int c1 = c0 + new_width; if ( (r0 >= height_) || (r1 > height_)) throw std::logic_error("SubMatrix: invalid row limits"); if ( (c0 >= width_) || (c1 > width_)) throw std::logic_error("SubMatrix: invalid column limits"); // count the number of nonzeros in the submatrix unsigned int new_size = 0; for (unsigned int c=c0; c != c1; ++c) { // number of nonzeros in source column c new_size += (col_offsets_[c+1] - col_offsets_[c]); } if (0u == new_size) throw std::logic_error("SparseMatrix::SubMatrix: submatrix is the zero matrix"); // allocate memory in the result; won't allocate if sufficient memory available result.Reserve(new_height, new_width, new_size); // Load the elements within the row and column bounds into the new matrix. // No need to call result.Clear(), since that will result in a new allocation. unsigned int* cols_b = result.ColBuffer(); unsigned int* rows_b = result.RowBuffer(); T* data_b = result.DataBuffer(); unsigned int count = 0; for (unsigned int c=c0; c != c1; ++c) { cols_b[c-c0] = count; unsigned int start = col_offsets_[c]; unsigned int end = col_offsets_[c+1]; for (unsigned int offset = start; offset != end; ++offset) { unsigned int row = row_indices_[offset]; if ( (row >= r0) && (row < r1)) { rows_b[count] = row - r0; data_b[count] = data_[offset]; ++count; } } } cols_b[c1] = count; //assert(new_size == count); // set the size of the new matrix explicitly, since Load() has been bypassed result.SetSize(count); }