void blRules()

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;
      }
    }
  }
}