How to handle indices of a 9-dimensional matrix
I am a physicist currently writing a C ++ program on multidimensional integration; in particular, the functions I am considering can have up to D = 9 dimensions.
Mathematically, I need to process an NxNxN ... xN matrix (D times), but from a programming perspective, I was tasked with using an array of NxNxN ... xN elements. From what I know, an array is better for generality and for all subsequent calculations using pointers.
However, I am now stuck with a problem that I cannot solve.
I need to do some calculations when one index of my matrix is โโfixed and all the others take all their different values.
If it were a 3x3x3 matrix, the code would be similar to the following:
double test[3][3][3];
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
test[0][i][j]=i*j;
}
}
i.e. I could fix the index and loop through the others. The same process can be extended to the second and third indexes.
How can I achieve the same effect using double test[3*3*3]
? Keep in mind that the 3D matrix is โโjust an example; the real matrices I am dealing with are 9-dimensional and so I need a general way of keeping the single index of my matrix and cycling all the others.
TL; DR : I have an array that represents an NxNxN ... xN matrix (9 times). I need to do some calculations on the array, as if one index of my matrix were fixed, and all the others were looped through all possible values.
I know there is a simple expression for the case where a 2D matrix is โโdisplayed in a 1-D array; does something like this exist here?
source to share
Raster scanning is the standard way to arrange items for two dimensions.
If you have a 2-D array test[3][3]
and you are accessing it test[i][j]
, then the corresponding one-dimensional array would be
double raster[3 * 3];
and you will access it like this:
raster[i * 3 + j];
This can be summarized in 3 dimensions:
double raster[3 * 3 * 3];
...
raster[a * 9 + b * 3 + c];
Or up to 9 measurements:
double raster[3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3];
...
raster[a * 6561 + b * 2187 + c * 729 + d * 243 + e * 81 + f * 27 + g * 9 + h * 3 + i];
If any of the constant index variables are a ... i
constant and change the rest in the loop, you will access the 8-D slice in your 9-D array.
You might want to define some struct
to hold all of these indices, for example:
struct Pos
{
int a, b, c, d, e, f, g, h, i;
};
Then you can easily convert the position to index from 1-D:
int index(Pos p)
{
return p.a * 6561 + p.b * 2187 + p.c * 729 + p.d * 243 + p.e * 81 + p.f * 27 + p.g * 9 + p.h * 3 + p.i;
}
source to share
Typically, a flattened array will contain its elements as follows: the elements of the last dimension will be mapped into repeating groups, with the innermost groups being the second dimension from the back, etc .:
values[x][y][z] => { x0 = { y0_0 = { z0_0_0, z0_0_1, ..., z0_0_N }, y0_1 = { z0_1_0, z0_1_1, ... }, ... y0_N }, x1 = ... }
values[x*y*z] => { z0_0_0, z0_0_1, ..., z0_0_N, z0_1_0, z0_0_1, ... }
I hope this makes sense outside of my brain.
So any access to an element will have to calculate how many blocks of elements are in front of it:
Access to [2][1][3]
means, skip 2 blocks x
, each containing y
blocks with elements z
, then pass another block y
containing elements z
, and access the 3rd element from the following block:
values[2 * y * z + 1 * z + 3];
More generally for N dimensions d1, d2, d3 .. dn
and an n-dimensional index i1, i2, .. iN
for access:
[i1 * d2 * ... * dN + i2 * d3 * ... * dN + ... + iN]
Let's go back to your example:
double test[3*3*3];
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
// test[0*3*3 + i*3 + j] = i * j;
test[i*3 + j] = i * j;
}
}
source to share