3

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

1 に答える 1