配列

d:id:konnyakmannan:20091212 をみて。
彼が FORTRAN の配列をどこで便利に感じているのかはわからないのだけれど、
C で任意次元配列をサブルーチンで扱うために一次元配列を利用するのを思いだした。
やり方は Row- and column-major order - Wikipedia
The N-dimensional array (ndarray) — NumPy v1.16 Manual
を見ればすぐわかる。
こんな指数を返す関数を作っておけばいい。C99 で書いてあるので注意。

// 総積の計算(多次元配列の全要素数を計算するのに使う)
int prod(const int* N, int rank){
    int prod = 1;
    for(int i=0; i<rank; ++i)
        prod *= N[i];
    return prod;
}
// 一次元配列の指数から多次元配列の指数を計算
void index_to_ndindex(int index, int* ndindex, int rank, const int* N){
    int base = index;
    for(int k=rank-1; k>=0; --k){
        ndindex[k] = base % N[k];
        base = (base - ndindex[k])/N[k];    
    }
}
// 多次元配列の指数から一次元配列の指数を計算
int index_from_ndindex(const int* ndindex, int rank, const int* N){
    int index = 0;
    int stride = 1;
    for(int k=rank-1; k>=0; --k){
        index += stride * ndindex[k];
        stride *= N[k];
    }
    return index;
}

例えば、三次元配列 A_{ijk} = ijk\quad i=0,\dots,4, j=0,\dots,5, k=0,\dots,2 を用意して、A_{431} を出力ってのを書くと。

int main(){
    const int rank = 3;
    const int N[] = {5, 6, 3};
    int size = prod(N, rank);
    double A[size];
    for(int i=0; i<size; ++i){
        int k[rank];
        index_to_ndindex(i, k, rank, N);
        A[i] = 1.0;
        for(int n=0; n<rank; ++n)
            A[i] *= k[n];
    }
    int k[] = {4, 3, 1};
    printf("%g\n", A[index_from_ndindex(k, rank, N)]);
}

FORTRAN で書いたルーチンを使うために column-major にするには、指数を返す関数内のループを逆に回せばいい。