mxm ブロックを nxn 行列に結合する関数を作成しています。ブロックは 3D ポインタ配列B[BlockIndex][BlockRow][BlockColumn]
で、nxn 行列は 2D ポインタ配列M[Row][Column]
です。M が 4x4 で B が 4 つの 2x2 行列の場合、BlockIndex = 0
は左上ブロック、BlockIndex = 1
は右上ブロック、 はBlockIndex = 2
左下ブロック、 は右下ブロックBlockIndex = 3
です。
M の要素を適切なブロックの行の先頭に向けたいだけですが、M の要素のアドレスを設定することはできないようです (可能かどうかもわかりません) [i][j]
。(2x2 と 4x4 の例を使用して) M の i 番目の行の最初の 2 つの要素は BlockIndex 番目のブロックの i 番目の行を指しますが、M の i 番目の行の 3 番目の要素を(BlockIndex+1)番目のブロック?M[i]
B[BlockIndex][i]
ここでは、メモリ内に並んで存在する 4 つの要素 (M の i 行目) の配列を取得し、その配列の最後の 2 つの要素を別の 2 つの要素の配列に変換します。ただし、これを回避できれば、要素ごとに B を M にディープ コピーすることに頼りたくないので、行列が巨大になるときに時間を節約できます。ここで「ディープコピー」を誤用している可能性があることにも気づきました...
明確にするために、(基本的に)X
最初の要素ではない配列の要素のアドレスを、別の配列(の最初の要素)のアドレスに変更したいと思いますY,Z
。この操作の後、 の要素を反復処理すると、X
さまざまなシーケンシャル メモリのセットにアクセスすることになりますX...Y...Z
。
以下は、マトリックスを小さなブロックに分割/結合するために書いている関数の現在の化身です。
ありがとう、
ティム
bool SplitCombineMat(double** &Mat, double*** &Blocks, int const& MatSize,
int const& BlockSize, bool const& SplitMatrix)
{
bool IsOk = true;
if (SplitMatrix)
IsOk = PrepareBlocks(Blocks, MatSize, BlockSize);
if (IsOk)
{
// Set the beginnings (pointers) of the rows of blocks
// to the right elements of Mat.
// This is a shallow copy.
int BlockIndex = 0;
for (int i = 0 ; i <= MatSize - BlockSize ; i += BlockSize)
for (int j = 0 ; j <= MatSize - BlockSize ; i += BlockSize){
for (int k = 0 ; k < BlockSize ; k++)
if (SplitMatrix)
Blocks[BlockIndex][k] = &Mat[k+i][j];
else // Here want to use pointers as above but can't figure it out...
// Something like -- &Mat[k+i][j] = Blocks[BlockIndex][k];
for (int l = 0 ; l < BlockSize ; l++)
Mat[k+i][l] = Blocks[BlockIndex][k][l];
BlockIndex++;
}
}
return IsOk;
}