#include <boost/iterator/counting_iterator.hpp>
#include <iostream>
template <typename T>
class Torus2D {
public:
using reference = T&;
public:
T v;
public:
reference getData() { return v; }
};
size_t numRows, numCols;
public:
using TorusNode = size_t;
using iterator = boost::counting_iterator<TorusNode>;
public:
Torus2D(size_t r, size_t c) : numRows(r), numCols(c) {
data.allocateInterleaved(r * c);
for (size_t n = 0; n < r * c; ++n) {
data.constructAt(n);
}
}
size_t height() { return numRows; }
size_t width() { return numCols; }
size_t size() { return width() * height(); }
iterator begin() { return iterator(0); }
iterator end() { return iterator(size()); }
void acquireNode(TorusNode n,
assert(n < size());
}
typename NodeData::reference
acquireNode(n, mflag);
return data[n].getData();
}
iterator upNeighbor(TorusNode n) {
auto r = n / numCols, c = n % numCols;
auto newR = (r + numRows - 1) % numRows;
return iterator(newR * numCols + c);
}
iterator downNeighbor(TorusNode n) {
auto r = n / numCols, c = n % numCols;
auto newR = (r + 1) % numRows;
return iterator(newR * numCols + c);
}
iterator leftNeighbor(TorusNode n) {
auto r = n / numCols, c = n % numCols;
auto newC = (c + numCols - 1) % numCols;
return iterator(r * numCols + newC);
}
iterator rightNeighbor(TorusNode n) {
auto r = n / numCols, c = n % numCols;
auto newC = (c + 1) % numCols;
return iterator(r * numCols + newC);
}
void
acquireAllNeighbors(TorusNode n,
acquireNode(*upNeighbor(n), mflag);
acquireNode(*downNeighbor(n), mflag);
acquireNode(*leftNeighbor(n), mflag);
acquireNode(*rightNeighbor(n), mflag);
}
};
int main(int argc, char* argv[]) {
if (argc < 4) {
std::cerr << "Usage: " << argv[0]
<< " <num_rows> <num_columns> <num_threads>" << std::endl;
return 1;
}
using Torus = Torus2D<unsigned int>;
using TorusNode = Torus::TorusNode;
Torus torus(std::atoi(argv[1]), std::atoi(argv[2]));
torus.size()),
[&](TorusNode n) { torus.getData(n) = 0; }
,
);
torus),
[&](TorusNode n, auto&) {
torus.acquireAllNeighbors(n);
torus.getData(*torus.upNeighbor(n)) += 1;
torus.getData(*torus.downNeighbor(n)) += 1;
torus.getData(*torus.leftNeighbor(n)) += 1;
torus.getData(*torus.rightNeighbor(n)) += 1;
},
,
size_t numWrongAnswer = 0;
for (auto n : torus) {
numWrongAnswer++;
}
}
std::cout << "# nodes of wrong answer: " << numWrongAnswer << std::endl;
return 0;
}