多次元配列の作り方

かんちんぷー

4×4の2次元配列を作るなら、16個の要素を格納できるメモリを確保して、インデクスを2つ指定すれば好きな要素にアクセスすることができます。

インデクスをi,jとすれば、以下のような計算でオフセットを求めます。

i * 4 + j(要素のサイズは除く)

指定するインデクスはそれぞれ0~3の範囲でなければ、意図しないメモリにアクセスしてしまいます。

指定されたインデクスを配列のサイズで割ったあまりを用いれば、意図しないメモリにアクセスしないで済みます。

3次元でも同じです。UxVxWの配列なら、インデクスi,j,kを用いて、以下省略、と。

i * U * V + j * V + k

n次元でもかんちんぷ~です。

さてこれは、1次元のメモリにn次元配列を格納するためのトリックです。実際、多くのメモリは2次元のアドレス指定(ロウとカラム)なので、屋上の上の屋根なわけですがね。それにしても、あたかもそこに多次元の配列があるかのように利用することが出来ます。たぶん、その先に1次元の構造があると考える必要すらないでしょう。

変換式の中のインデクスの並べ方で、メモリ上の各要素の配置は変わってきますが、インデクス指定でアクセスする限りそれはどうでもいいことです。なにしろ読み取りヘッドの移動は、移動距離に関係なく一定であると定義された世界ですから。

しかし実際には、距離が異なれば、読み取りヘッドの移動にかかるコストが変わります。アクセスにかかる時間が変わるわけです。

インデクス指定のみに意味があると考えるなら、どうでもいいことです。実際、インデクスを利用している側からすればもっともなことです。

インデクス指定しかアクセスする手段がない場合でも、インデクスを変化させながらアクセスしてみれば、内部でどのような変換が行われているかをある程度調べることができるでしょう。

もしアクセスしているメモリが仮想メモリであり、その向こう側にテープドライブが隠れていたとしても、アクセスすることを通じて、向こう側を覗くことはできるというわけです。

10とか20次元の配列を考えると、係数が巨大になるインデクスが現れます。配列のサイズに寄りますが、巨大な係数に対応するインデクスを変更すると、アクセスは『重く』なります。

知る必要があるのは、

  • どのインデクスが、『重い』のかどうか
  • 配列の各次元のサイズはどれくらいか

です。

観念上の数直線は連続であり、いくらでも細かい目盛りを振ることができます。実際にはそうではありません。インデクスは有限であり、必要な配列のサイズも有限です。

最後に。インデクスを利用側に丸めて指定させるのはナンセンスです。向こう側で勝手に丸めても、利用する側には気づかれないでしょう。サイズが巨大ならなおさらです。配列の『果て』を調べようとあるインデクスをひたすら増やしていって、反対側に突き抜けてしまっても、利用する側にとってはどうでもいいことかもしれません。

彼らの興味は先に挙げたことであり、『配列をどうやったら作れるか』、ではないからです。