Edit: It seems I misinterpreted the question. However the below answer is still relevant to the topic, so I am not going to remove it for now.
The answer could be specific to the problem, perhaps the code for permuting d == 2
can be reduced to the same as d == 3
. I don't know exactly what the code would look like as I have not studied tensors, but if it is not reducible then the "dirty" method that you have is your best option.
Alternatively, if you have the number of dimensions #define
d similar to the pointer representation in the post you link, you could use pre-processor directives to turn on/off extra loops. This should give you a bit more condensed code. it should probably look like:
#define D 4 // Number of dimensions to use
#define MAX_D 10 // maximum # of dimensions
...
#if D >= MAX_D
for(int i = 0; i < dimensions[MAX_D - 1]; i++) {
#endif
...
#if D >= 2
for(int i = 0; i < dimensions[1]; i++) {
#endif
// Base case ; D == 1
for(int i = 0; i < dimensions[0]; i++) {
// Permutation stuff here
}
#if D == 2
}
#elif D == 3
}}
#elif D == 4
}}}
....
#endif
While this is a bit ugly, it prevents you from having to create and maintain a bunch of different versions.
The link provided is really the best approach for creating a d-dimensional pointed in C. However, you can simulate a d-dimensional array with a 1-D array and a bit of math.
You can use the following functions to achieve this:
void get(int *d_dimens, int d, size_t *dimensions, size_t *point, int val) {
size_t index = 0; // Index of the number
size_t dim = 1; // Location of the current dimension
for(int i = 0; i < d; i++) {
index += point[i] * dim;
dim *= dimensions[i];
}
return d_dimens[index];
}
void set(int *d_dimens, int d, size_t *dimensions, size_t *point, int val) {
size_t index = 0; // Index of the number
size_t dim = 1; // Location of the current dimension
for(int i = 0; i < d; i++) {
index += point[i] * dim;
dim *= dimensions[i];
}
d_dimens[index] = val;
}
int *create(int d, size_t *dimensions) {
sizt_t num_elems = 1;
for(int i = 0; i < d; i++)
num_elems *= dimensions[i];
int *ptr = malloc(sizeof (int) * num_elems);
return ptr;
}
Where dimensions
is an array of dimensions, d_dimens
is the 1-D array we are using to simulate a d-D array, and d
is the number of dimensions. For example if you want a 4x5x2 array, you would use dimensions = {4, 5, 2}; d = 3;