SparseMat::SparseMat(const SparseMat &source, const DoFMap &rowmap, const DoFMap &colmap) : nnz_(0), nrows_(rowmap.range()), ncols_(colmap.range()), consolidated_(true) // true, because mtx is initially empty { data.resize(nrows_); nonempty_col.resize(ncols_, false); for(SparseMatConstIterator ij=source.begin(); ij<source.end(); ++ij) { assert(ij.row() < rowmap.domain()); // row is unsigned, dont check >= 0 int i = rowmap[ij.row()]; assert(data.size()!=0 || i==-1); assert(i < (int) rowmap.range()); if(i >= 0) { assert(ij.col() < colmap.domain()); int j = colmap[ij.col()]; assert(j < (int) colmap.range() && j >= -1); if(j >= 0) { insert(i, j, *ij); // unsets consolidated_. } } } consolidate(); }
SparseMat SparseMat::operator*(const SparseMat &right) const { if(!consolidated() || !right.consolidated()) throw ErrProgrammingError("Attempt to multiply unconsolidated SparseMats!", __FILE__, __LINE__); SparseMat result(nrows(), right.ncols()); const SparseMat rightt = right.transpose(); for(unsigned int i=0; i<nrows(); i++) { for(unsigned int j=0; j<rightt.nrows(); j++) { const_row_iterator ai = begin(i); const_row_iterator bj = rightt.begin(j); while(ai < end(i) && bj < rightt.end(j)) { if(ai.col() == bj.col()) { result.insert(i, j, (*ai)*(*bj)); ++ai; ++bj; } else if(ai.col() < bj.col()) ++ai; else ++bj; } } result.consolidate_row(i); } // result.consolidate(); result.consolidated_ = true; return result; }
/* multiplication between sparse and classic matrix A=D*Q * hists: sparse matrix (typically matrix of database words) * nhist: matrix (typically matrix of query words) * return: hists*nhists (matrix) */ Mat mul(const SparseMat &hists, const Mat &nhist) { Mat answer = Mat::zeros(hists.size(0),1,CV_32F); SparseMatConstIterator it = hists.begin(), it_end = hists.end(); for (; it!=it_end;++it) { const SparseMat::Node* n = it.node(); answer.at<float>(n->idx[0])+=nhist.at<float>(n->idx[1])*it.value<float>(); } return answer; }
void SparseMat::tile(unsigned int i, unsigned int j, const SparseMat &other) { // Add other to this, offset by i rows and j columns. assert(i + other.nrows() <= nrows()); assert(j + other.ncols() <= ncols()); for(SparseMat::const_iterator kl = other.begin(); kl<other.end(); ++kl) { unsigned int ii = kl.row() + i; unsigned int jj = kl.col() + j; assert(0 <= ii && ii < nrows_); assert(0 <= jj && jj < ncols_); insert(ii, jj, *kl); } }
void mmadump(const std::string &filename, const std::string &mtxname, const SparseMat &m) { std::ofstream os(filename.c_str()); os << mtxname << " = Table[Table[0, {i, 1, " << m.ncols() << "}], {j, 1, " << m.nrows() << "}]" << std::endl; for(SparseMat::const_iterator ij=m.begin(); ij<m.end(); ++ij) { std::string val(to_string(*ij)); int epos = val.find("e"); if(epos >= 0) val.replace(epos, 1, "*^"); os << mtxname << "[[" << ij.row()+1 << "," << ij.col()+1 << "]] = " << val << std::endl; } os.close(); }
void CmShow::showTinySparseMat(CStr &title, const SparseMat &A1d) { int N = A1d.nzcount(); if (N > 1000) return; struct NodeSM { int r, c; double v; bool operator < (const NodeSM &n) { if (r < n.r) return true; else if (r > n.r) return false; else return c < n.c; } void print() { if (abs(v) > 1e-8) printf("(%d, %d) %-12g\t", r, c, v); } }; vector<NodeSM> nodes(N); SparseMatConstIterator it = A1d.begin(); for (int i = 0; i < N; i++, ++it) { const int* idx = it.node()->idx; nodes[i].r = idx[0] + 1; nodes[i].c = idx[1] + 1; nodes[i].v = it.value<double>(); } sort(nodes.begin(), nodes.end()); for (int i = 0; i < N; i++) nodes[i].print(); printf("\n"); Mat m; A1d.convertTo(m, CV_64F); showTinyMat(title, m); }