Program Listing for File rcm_reorder.cc
↰ Return to documentation for file (src/sparsebase/reorder/rcm_reorder.cc
)
#include "sparsebase/reorder/rcm_reorder.h"
#include <queue>
#include "sparsebase/format/csr.h"
namespace sparsebase::reorder {
template <typename IDType, typename NNZType, typename ValueType>
RCMReorder<IDType, NNZType, ValueType>::RCMReorder() {
this->RegisterFunction(
{format::CSR<IDType, NNZType, ValueType>::get_id_static()},
GetReorderCSR);
}
template <typename IDType, typename NNZType, typename ValueType>
RCMReorder<IDType, NNZType, ValueType>::RCMReorder(RCMReorderParams p) {
this->RegisterFunction(
{format::CSR<IDType, NNZType, ValueType>::get_id_static()},
GetReorderCSR);
}
template <typename IDType, typename NNZType, typename ValueType>
IDType RCMReorder<IDType, NNZType, ValueType>::peripheral(NNZType *xadj,
IDType *adj, IDType n,
IDType start,
SignedID *distance,
IDType *Q) {
IDType r = start;
SignedID rlevel = -1;
SignedID qlevel = 0;
while (rlevel != qlevel) {
// cout << "Finding peripheral: current dist = " << qlevel << std::endl;;
rlevel = qlevel;
for (IDType i = 0; i < n; i++) distance[i] = -1;
IDType qrp = 0, qwp = 0;
distance[r] = 0;
Q[qwp++] = r;
while (qrp < qwp) {
IDType u = Q[qrp++];
for (NNZType ptr = xadj[u]; ptr < xadj[u + 1]; ptr++) {
IDType v = adj[ptr];
if (distance[v] == (IDType)-1) {
distance[v] = distance[u] + 1;
Q[qwp++] = v;
}
}
}
qlevel = 0;
for (IDType i = 0; i < qrp; i++) {
if (qlevel < distance[Q[i]]) {
qlevel = distance[Q[i]];
r = Q[i];
}
}
}
return r;
}
template <typename IDType, typename NNZType, typename ValueType>
IDType *RCMReorder<IDType, NNZType, ValueType>::GetReorderCSR(
std::vector<format::Format *> formats, utils::Parameters *params) {
format::CSR<IDType, NNZType, ValueType> *csr =
formats[0]->AsAbsolute<format::CSR<IDType, NNZType, ValueType>>();
NNZType *xadj = csr->get_row_ptr();
IDType *adj = csr->get_col();
IDType n = csr->get_dimensions()[0];
IDType *Q = new IDType[n];
IDType *Qp = new IDType[n];
SignedID *distance = new SignedID[n];
IDType *V = new IDType[n];
for (IDType i = 0; i < n; i++) V[i] = 0;
std::priority_queue<std::pair<IDType, IDType>> PQ;
int qrp = 0, qwp = 0;
IDType reverse = n - 1;
for (IDType i = 0; i < n; i++) {
if (V[i] == 0) {
if (xadj[i] == xadj[i + 1]) {
Q[reverse--] = i;
V[i] = 1;
continue;
}
// cout << i << std::endl;
IDType perv = peripheral(xadj, adj, n, i, distance, Qp);
V[perv] = 1;
Q[qwp++] = perv;
while (qrp < qwp) {
IDType u = Q[qrp++];
for (IDType ptr = xadj[u]; ptr < xadj[u + 1]; ptr++) {
IDType v = adj[ptr];
if (V[v] == 0) {
PQ.push(std::make_pair(xadj[v + 1] - xadj[v], v));
V[v] = 1;
}
}
while (!PQ.empty()) {
Q[qwp++] = PQ.top().second;
;
PQ.pop();
}
}
}
}
// Reverse
for (IDType i = 0; i < n / 2; i++) {
Qp[i] = Q[n - i - 1];
Qp[n - i - 1] = Q[i];
}
// Place it in the form that the transform function takes
for (IDType i = 0; i < n; i++) {
Q[Qp[i]] = i;
}
delete[] Qp;
delete[] distance;
delete[] V;
return Q;
}
#if !defined(_HEADER_ONLY)
#include "init/rcm_reorder.inc"
#endif
} // namespace sparsebase::reorder