c++sparse-matrix

Transpose modifed CSR format (C++)


I'm trying to transpose matrix (GF(2) field, so no need to store elements) that is written in modifed CSR format:

class GF2_CSR_Matrix
{
protected:
    uint64_t rows;
    uint64_t columns;
    uint64_t non_zero;
    std::vector<uint64_t> nonzeros_per_row; (Here each element is only number of NZ in row, unlike classical CSR which stores total NZ in rows before)
    std::vector<uint64_t> column_indexes; (idx of columns containing NZ)
}

Also I have parallelized function to count partial sum.

void calculate_prefix_sum(std::vector<std::pair<uint64_t, uint64_t>> &j_ends,
                          const std::vector<uint64_t> &nonzeros_per_row) // .first is start of indexing, .second is end. In fact [i].second equals [i+1].first

Can somebody help me?


Solution

  • Something along these lines (not tested):

    // Eventually, will have a count of non-zero elements
    // in all columns to the left of `col`.
    // But first, just count non-zeros per column.
    std::vector<uint64_t> cumulative_nonzeros_per_column(columns, 0);
    for (uint64_t col : column_indexes) {
      ++cumulative_nonzeros_per_column[col];
    }
    // Now convert to cumulative counts.
    uint64_t cumulative_count = 0;
    for (uint64_t& col_count : cumulative_nonzeros_per_column) {
      uint64_t prev_count = cumulative_count;
      cumulative_count += col_count;
      col_count = prev_count;
    }
    
    std::vector<uint64_t> row_indexes(non_zero);
    std::vector<uint64_t> nonzeros_per_column(columns, 0);
    uint64_t row = 0;
    uint64_t nz_in_row = 0;
    for (uint64_t col : column_indexes) {
      for (;;) {
        if (++nz_in_row <= nonzeros_per_row[row]) break;
        ++row;
        nz_in_row = 0;
      }
      // How many non-zero elements would precede this element in column-wise
      // traversal? The cumulative count in all columns to the left, plus the
      // count encountered so far in the current column.
      row_indexes[cumulative_nonzeros_per_column[col] +
                  nonzeros_per_column[col]++] = row;
      
    }
    
    // row_indexes becomes column_indexes of the transposed matrix
    // nonzeros_per_row becomes nonzeros_per_column of the transposed matrix