in sparseconvnet/SCN/Metadata/IOLayersRules.h [135:288]
void blRules(SparseGrids<dimension> &SGs, RuleBook &rules, long *coords,
Int batchSize, Int length, Int mode, Int &nActive) {
assert(nActive == 0);
assert(rules.size() == 0);
assert(SGs.size() == 0);
SGs.resize(batchSize);
Int I;
if (mode == 0) {
nActive = batchSize * length;
rules.resize(1);
rules[0].push_back(mode);
rules[0].push_back(1);
rules[0].push_back(batchSize);
rules[0].push_back(length);
rules[0].push_back(nActive);
#pragma omp parallel for private(I)
for (I = 0; I < batchSize; I++) {
auto &sg = SGs[I];
sg.ctr = I * length;
auto c = coords + I * length * dimension;
Point<dimension> p;
for (Int l = 0; l < length; ++l) {
for (Int j = 0; j < dimension; ++j)
p[j] = c[j];
c += dimension;
sg.mp[p] = l;
}
}
return;
}
if (mode <= 2) {
// Compile list of how input rows correspond to output rows
std::vector<std::vector<Int>> outputRows(batchSize);
std::vector<Int> nActives(batchSize);
#pragma omp parallel for private(I)
for (I = 0; I < batchSize; I++) {
auto &sg = SGs[I];
auto &ors = outputRows[I];
auto &nAct = nActives[I];
auto c = coords + I * length * dimension;
Int i = I * length;
Point<dimension> p;
if (mode == 1) {
for (Int l = 0; l < length; ++l, ++i) {
for (Int j = 0; j < dimension; ++j)
p[j] = *c++;
if (p[0] >= 0) {
if (sg.mp.insert(make_pair(p, nAct)).second) {
nAct++;
ors.push_back(i);
} else {
ors[sg.mp[p]] = i;
}
}
}
}
if (mode == 2) {
for (Int l = 0; l < length; ++l, ++i) {
for (Int j = 0; j < dimension; ++j)
p[j] = *c++;
if (p[0] >= 0) {
if (sg.mp.insert(make_pair(p, nAct)).second) {
nAct++;
ors.push_back(i);
}
}
}
}
}
for (I = 0; I < batchSize; I++) {
SGs[I].ctr = nActive;
nActive += nActives[I];
}
Int maxActive = 1;
rules.resize(2);
rules[0].push_back(mode);
rules[0].push_back(maxActive);
rules[0].push_back(batchSize);
rules[0].push_back(length);
rules[0].push_back(nActive);
auto &rule = rules[1];
rule.resize(2 * nActive);
#pragma omp parallel for private(I)
for (I = 0; I < batchSize; I++) {
auto &ors = outputRows[I];
auto rr = &rule[SGs[I].ctr * 2];
for (auto &row : ors) {
rr[0] = 1;
rr[1] = row;
rr += 2;
}
}
return;
}
if (mode == 3 or mode == 4) {
// Compile list of how input rows correspond to output rows
std::vector<std::vector<std::vector<Int>>> outputRows(batchSize);
std::vector<Int> nActives(batchSize);
#pragma omp parallel for private(I)
for (I = 0; I < batchSize; I++) {
auto &sg = SGs[I];
auto &ors = outputRows[I];
auto &nAct = nActives[I];
auto c = coords + I * length * dimension;
Int i = I * length;
Point<dimension> p;
for (Int l = 0; l < length; ++l, ++i) {
for (Int j = 0; j < dimension; ++j)
p[j] = *c++;
if (p[0] >= 0) {
if (sg.mp.insert(make_pair(p, nAct)).second) {
nAct++;
ors.resize(nAct);
}
ors[sg.mp[p]].push_back(i);
}
}
}
for (I = 0; I < batchSize; I++) {
SGs[I].ctr = nActive;
nActive += nActives[I];
}
Int maxActive = 1;
if (mode >= 3)
for (auto &ors : outputRows)
for (auto &row : ors)
maxActive = std::max(maxActive, (Int)row.size());
rules.resize(2);
rules[0].push_back(mode);
rules[0].push_back(maxActive);
rules[0].push_back(batchSize);
rules[0].push_back(length);
rules[0].push_back(nActive);
auto &rule = rules[1];
rule.resize((maxActive + 1) * nActive);
#pragma omp parallel for private(I)
for (I = 0; I < batchSize; I++) {
auto &ors = outputRows[I];
auto rr = &rule[SGs[I].ctr * (maxActive + 1)];
for (auto &row : ors) {
rr[0] = row.size();
for (Int i = 0; i < (Int)row.size(); ++i)
rr[i + 1] = row[i];
rr += 1 + maxActive;
}
}
}
}