Допустим, у нас есть сетка nxm. Мы хотим разделить сетку на bxb-блоки. Необходимо, чтобы n% b = 0 и m% b = 0.
. Назовем общие индексы I = 0, ..., n-1 и J = 0, ..., m-1. и индексы в блоке i = 0, ..., b-1 и j = 0, ..., b-1.
Я попытался набросать макет здесь .
Учитывая I, индекс столбца блока равен (I / b), а индекс внутри блока i = I% b. Индекс строки блока равен (J / b), а индекс в блоке j = J% b.
Каждый полный блок содержит b * b элементов. Таким образом, полный ряд блоков содержит (n / b) b b = n * b элементов.
Объединение всех вместе линейного индекса элемента (I, J):
- (I% b) [столбец в блоке, предшествующем элементу]
- + (J% b) * b [строки в блоке, предшествующем элементу]
- + (I / b) * b * b [столбец блоков, предшествующих блоку элемента]
- + (J / b) * n * b [ряд блоков, предшествующих блоку элемента]
Грубый эскиз класса заблокированной сетки размера во время выполнения:
template <typename T>
class Block_Grid
{
public:
Block_Grid(std::size_t n, std::size_t m, std::size_t b)
: _n(n), _m(m), _b(b), _elements(n * m)
{
assert(n % b == 0);
assert(m % b == 0);
}
T & operator()(std::size_t i, std::size_t j)
{
return _elements[index(i, j)];
}
protected:
private:
std::size_t index(int i, int j) const
{
return (i % b)
+ (j % b) * b
+ (i / b) * b * b
+ (j / b) * n * b;
}
std::size_t _n;
std::size_t _m;
std::size_t _b;
std::vector<T> _elements;
};
или класса размера компиляции
template <typename T, std::size_t N, std::size_t M, std::size_t B>
class Block_Grid
{
static_assert(N % B == 0);
static_assert(M % B == 0);
public:
Block_Grid() = default;
T & operator()(std::size_t i, std::size_t j)
{
return _elements[index(i, j)];
}
protected:
private:
std::size_t index(std::size_t i, std::size_t j) const
{
return (i % B) + (j % B) * B + (i / B) * B * B + (j / B) * N * B;
}
std::array<T, N * M> _elements;
};